25. Fejezet. Parancssori programozás a PHP-ben

A 4.3-as verziótól felfelé a PHP támogat egy új SAPI (Server Application Programming Interface) típust, a CLI-t ami a Command Line Interface rövidítése. A nevéből következik, hogy ez a SAPI típus leginkább shell (vagy akár desktop!) alkalmazások fejlesztéséhez használatos a PHP-ben. Van néhány különbség a CLI SAPI és a többi SAPI között, ezek magyarázatára a későbbiekben rátérünk.

A CLI SAPI először a PHP 4.2.0 verziójában jelent meg, de akkor még csak kísérleti jelleggel. Használatához a --enable-cli kapcsolóval kellett indítani a ./configure scriptet installáláskor. A PHP 4.3.0 megjelenésétől megszűnt a kísérleti státusz és a CLI SAPI mindig beépül a php futtatható binárisba. (Windows alatt ez a php.exe)

Lényegesebb különbségek a CLI SAPI és a többi SAPI között:

Az alábbi listát a parancssori opciókról a PHP generálta. Ezt bármikor kilistáztathatod ha a PHP-t a -h kapcsolóval indítod parancssorból:
Usage: php [options] [-f] <file> [args...]
       php [options] -r <code> [args...]
       php [options] [-- args...]
  -s               Display colour syntax highlighted source.
  -w               Display source with stripped comments and whitespace.
  -f <file>        Parse <file>.
  -v               Version number
  -c <path>|<file> Look for php.ini file in this directory
  -a               Run interactively
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -z <file>        Load Zend extension <file>.
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -i               PHP information
  -r <code>        Run PHP <code> without using script tags <?..?>
  -h               This help

  args...          Arguments passed to script. Use -- args when first argument 
                   starts with - or script is read from stdin

A CLI SAPI-val háromféleképpen indíthatsz el egy PHP programot:

  1. Hogyan lehet a PHP-vel fájlokat futtatni.

    php my_script.php
    
    php -f my_script.php
    Mindkét módon (használva a -f kapcsolót vagy nem) futtatja a my_script.php nevű szkriptet. Bármit futtathatsz, a PHP szkriteknek nem muszáj .php kiterjesztésűeknek lenniük, bármilyen nevű és kiterjesztésű fájl futtatható.

  2. PHP kód futtatása közvetlenül a parancssorból.

    php -r 'print_r(get_defined_constants());'
    Különösen figyelni kell a shell változók helyettesítésére és az idézőjelekre!

    Megjegyzés: A példát figyelmesen szemlélve észrevehetjük, hogy nincsenek nyitó és záró tagok. Az -r kapcsolóval ezekre nincs szükség. Ha mégis használod őket, az hibához fog vezetni.

  3. PHP kód futtatása a standard inputon (stdin) keresztül.

    Ez a módszer dinamikussá teszi a PHP kód létrehozását és egyből a futtatható binárisba táplálja a kódot, amint a következő (képzeletbeli) példában láthatjuk:
    $ valami_szkript | valami_filter | php | sort -u >eredmeny.txt

A három programfuttatási módszert nem lehet egymással kombinálni.

Mint minden shellprogram, a PHP bináris, így az általad írt PHP szkript képes argumentumokat feldolgozni. Bármennyi argumentumot megadhatsz a szkriptednek, ezek számát nem korlátozza a PHP (A shellben van egy bizonyos határ a megadható argumentumok számát illetően, de az általában bőségesen elég). A szkriptnek átadott argumentumokat a $argv globális tömb tartalmazza. A tömb nulladik eleme mindig a szkript neve. (Ez a - karakterjel abban az esetben, ha a PHP kód az -r kapcsolóval lett indítva a parancssorból.) A másik globális tömb a $argc, ami a $argv tömb elemeinek számát tartalmazza (De ez NEM egyenlő a szkriptnek átadott argumentumok számával!).

Amikor különféle opciókkal akarod futtatni egy szkriptet, az argumentumoknak nem szabad - karakterrel kezdődniük. Ha mégis kiteszed a - jelet, akkor abból könnyen probléma lehet, mert a PHP úgy veszi, mintha a saját opciói közül adnál meg egyet. Hogy ezt elkerüld, használd a -- szeparátort. Ez esetben a PHP az argumentumokat változtatás nélkül továbbítja a szkriptnek.

# Ez nem fogja futtatni a megadott kódot, csak szemléltetésre jó.
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]

# Ez átadja a szkriptnek a '-h' argumentumot és megakadályozza a PHP-t abban,
# hogy a sajátjának higgye. 
$ php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}

Habár, van egy másik módja a PHP paracssori futtatásának. Lehet írni olyan programokat, melyek a #!/usr/bin/php sorral kezdődnek és ezt követi a "normál" PHP kód, a szabványos PHP kezdő-és záró tagokkal (valamint a fájl futtatási paramétereinek a beállításai). Ezzel a módszerrel úgy futtathatjuk programunkat, mint egy normál shell vagy Perl szkriptet:
#!/usr/bin/php
<?php
    var_dump
($argv);
?>
Feltéve, hogy ennek a fájlnak test a neve (és az éppen aktuális könyvtárunkban van, Linux alatt), a következőket tehetjük:
$ chmod 755 test
$ ./test -h -- foo
array(4) {
  [0]=>
  string(6) "./test"
  [1]=>
  string(2) "-h"
  [2]=>
  string(2) "--"
  [3]=>
  string(3) "foo"
}
Látható, hogy ebben az esetben semmi problémát nem okozott az, hogy a szkriptnek a - karakterrel adtuk át az argumentumokat.

Táblázat 25-3. Parancssori opciók

OpcióLeírás
-s

Színesben kiemelt forrását írja ki a szkriptnek.

Ez az opció egy saját algoritmust használ a fájl elemzéséhez, amivel HTML kódot generál a forrásból a standard kimenetre. Ez a kód tartalmazza a színes kiemeléshez szükséges és az egyéb formázó tag-eket, a szabványos <code> [...] </code> HTML formában, de nem tartalmazza a HTML fejléceket.

Megjegyzés: Ez az opció nem hazsnálható együtt az -r kapcsolóval.

-w

Kommentek és felesleges sorközök nélkül listázza ki a kódot.

Megjegyzés: Ez az opció nem használható együtt az -r kapcsolóval.

-f

Értelmezi és futtatja az -f kapcsoló után megadott fájlot. Ez a kapcsoló opcionális és el lehet hagyni, ha pusztán a fájlnév elegendő a fájl futtatásához.

-v

Kiírja a PHP, PHP SAPI, és a Zend verziószámát a standard kimenetre, pl:
$ php -v
PHP 4.3.0-dev (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.2.1, Copyright (c) 1998-2002 Zend Technologies

-c

Ha nem a megszokott helyén van, akkor megadhatjuk ezzel a kapcsolóval, hogy hol a php.ini vagy megadhatunk egy saját INI fájlot (aminek nem muszáj php.ini nevet adni!), pl..:
#ezzel megmondjuk a PHP-nek, hogy a /saját/könyvtárban találja a php.ini-t
$ php -c /saját/könyvtár/ maszek.php

#ez pedig utasítja PHP-t, hogy a /saját/könyvtárban/ levő saját.ini-t
#vegye alapul a maszek.php szkript futtatásakor.
$ php -c /saját/könyvtár/saját.ini maszek.php

-a

Interaktívan futtatja a PHP-t.

-d

Ezzel az opcióval bármilyen konfigurációs utasítást, ami csak a php.ini-ben megtalálható, egy saját értékkel érvényesíthetünk a szkript futásának idejére. Az általános formája a következő:
-d konfigurációs_utasítás[=érték]

Példák:
# Az értéket elhagyva a megadott konfigurációs utasításhoz az "1" értéket
# rendeli.
$ php -d max_execution_time -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"

# Ha csak egy szóközt nyomunk az érték helyett, akkor a konfigurációs
# utasításnak az "" értéket adja.
php -d max_execution_time= -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""

# A konfigurációs utasítás értéke az lesz, amit az egyenlőségjel után írunk: 
$  php -d max_execution_time=20 -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$  php -d max_execution_time=fogalmamsincsen -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "fogalmamsincsen"

-e

A hibakeresést segíti részletes információk kiírásával.

-z

Betölti a Zend bővítményt. Ha csak a futtatandó szkript nevét adtuk meg utána, akkor a PHP megpróbálja ezt a bővítményt a rendszereden alapértelmezett függvéykönyvtár (library) útvonal alapján betölteni (Ez általában az /etc/ld.so.conf fájlban van definiálva a Linux rendszereken). Ha megadsz egy konkrét útvonalat, akkor a PHP ezt veszi alapul, nem pedig a rendszer általit. Relatív útvonalat is megadhatsz a PHP-nek, hogy az aktuális könyvtárhoz képest hol keresse a bővítményt.

-l

Segítségével kényelmesen elvégezhető a szintaktikai ellenőrzés egy megadott PHP kódon. Ha nincs hiba, a standard kimenetre kiírja, hogy No syntax errors detected in <filename> És a shell visszatérési értéke 0. Hiba esetén a szöveg Errors parsing <filename>, majd kiírja a standard kimenetre a megérdemelt hibaüzenetet és a shell visszatérési értéke 255 lesz.

Ez az opció nem jelzi a végzetes hibákat (mint pl. egy definiálatlan függvény). Használd ezt az -f kapcsolóval együtt, ha végzetes hibákat is akarsz találni. ;)

Megjegyzés: Ez az opció nem használható együtt az -r kapcsolóval.

-m

Eme opció használatával a PHP kilistázza a beépített (és betöltött) PHP és Zend modulokat:
$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

-i Ez a parancsori opció meghívja a phpinfo() függvényt és kiírja az eredményét. Ha a PHP furcsán viselkedik, ajánlatos kiadni a parancssorban egy php -i-t és figyelmesen elolvasni a hibaüzeneteket a táblázatokban. Készülj fel rá, hogy a kimenet HTML formázott, így a parancssorban szinte olvashatatlan. (Irányítsd át a kimenetet egy HTML fájlba (php -i >phpinfo.html) és nézd meg egy böngészővel.)
-r

Ez az opció teszi lehetővé, hogy PHP parancsokat adjunk ki közvetlenül a parancssorból. A kezdő és a záró PHP tagok (<?php és ?>) NEM KELLENEK és hibához fog vezetni, ha mégis alkalmazod őket.

Megjegyzés: Óvatosan kell bánni ezzel a parancssori PHP futtatási módszerrel, nehogy a változó helyettesítés miatt összeakadjon a shellel.

Példa egy ilyen hibára
$ php -r "$foo = get_defined_constants();"
Command line code(1) : Parse error - parse error, unexpected '='
Itt az a probléma, hogy az sh/bash shell elvégezte a változó helyettesítést mert dupla idézőjeleket " használtunk. Mivel azonban a $foo nem definiált, a shell behelyettesíti egy üres értékre, vagyis az a helyzet, mintha a következő parancsot adtuk volna ki a PHP-nek:
$ php -r " = get_defined_constants();"
Az a helyes megoldás, ha egyszerű idézőjeleket (') használunk. Az ilyen idézőjelek közé írt változókkal nem foglalkozik az sh/bash.
$ php -r '$foo = get_defined_constants(); var_dump($foo);'
array(370) {
  ["E_ERROR"]=>
  int(1)
  ["E_WARNING"]=>
  int(2)
  ["E_PARSE"]=>
  int(4)
  ["E_NOTICE"]=>
  int(8)
  ["E_CORE_ERROR"]=>
  [...]
Ha nem sh/bash, shellt használsz, a hibákat és tapasztalataidat bátran oszd meg velünk egy emailben: phpdoc@lists.php.net. Problémákat okozhat, ha shell változókat akarsz a kódba integrálni vagy blackslahes-eket használni.

-h Ezzel az opcióval lehet információt szerezni az aktuális parancssori opciókról és néhány sornyi magyarázatot hozzájuk.

The PHP executable can be used to run PHP scripts absolutely independent from the web server. If you are on a Unix system, you should add a special first line to your PHP script, and make it executable, so the system will know, what program should run the script. On a Windows platform you can associate php.exe with the double click option of the .php files, or you can make a batch file to run the script through PHP. The first line added to the script to work on Unix won't hurt on Windows, so you can write cross platform programs this way. A simple example of writing a command line PHP program can be found below.

Példa 25-1. Script intended to be run from command line (script.php)

#!/usr/bin/php
<?php

if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
?>

This is a command line PHP script with one option.

  Usage:
  <?php echo $argv[0]; ?> <option>

  <option> can be some word you would like
  to print out. With the --help, -help, -h,
  or -? options, you can get this help.

<?php
} else {
    echo
$argv[1];
}
?>

In the script above, we used the special first line to indicate, that this file should be run by PHP. We work with a CLI version here, so there will be no HTTP header printouts. There are two variables you can use while writing command line applications with PHP: $argc and $argv. The first is the number of arguments plus one (the name of the script running). The second is an array containing the arguments, starting with the script name as number zero ($argv[0]).

In the program above we checked if there are less or more than one arguments. Also if the argument was --help, -help, -h or -?, we printed out the help message, printing the script name dynamically. If we received some other argument we echoed that out.

If you would like to run the above script on Unix, you need to make it executable, and simply call it as script.php echothis or script.php -h. On Windows, you can make a batch file for this task:

Példa 25-2. Batch file to run a command line PHP script (script.bat)

@c:\php\php.exe script.php %1 %2 %3 %4

Assuming, you named the above program as script.php, and you have your php.exe in c:\php\php.exe this batch file will run it for you with your added options: script.bat echothis or script.bat -h.

See also the Readline extension documentation for more functions you can use to enhance your command line applications in PHP.