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. Nem árt megjegyezni, hogy a CLI és a CGI két különböző SAPI bár elég hasonló a viselkedésmódjuk.
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 CLI SAPI kísérleti státusza és a --enable-cli alapértelmezésben be van állítva. Kikapcsolásához a --disable-cli konfigurációs paramétert használhatod.
A PHP 4.3.0-tól a CLI/CGI binárisok neve, helye és létezése függ attól, hogyan lett a PHP telepítve. Alapértelmezésben, a make parancs végrehajtásakor, a CGI és a CLI is létre lesz hozva és a sapi/cgi/php illetve a sapi/cli/php könytárakba lesznek helyezve a PHP forráskönyvtáron belül. Észreveheted, hogy mindkettőnek a neve php. Ami a make install folyamán történik, az a configure opcióktól függ. Ha ki lett választva egy SAPI modul, mint pl. aspx, vagy a --disable-cgi meg volt adva, akkor a make install idejére a {PREFIX}/bin/php helyen a CLI lesz, egyébként pedig a CGI-t teszi oda. Például ha --with--apxs benne van a configure sorban, akkor a CLI-t másolja a {PREFIX}/bin/php helyre a make install idejére. Ha felül akarod bírálni a CGI bináris telepítését, akkor a make install után add ki a make install-cli parancsot. Egy másik lehetőség, hogy megadod a --disable-cgi configure opciót.
Note: Mivel mind a --enable-cli mind a --enable-cgi alapértelmezésben be van állítva, az, hogy a configure sorban az --enable-cli meg van adva, nem feltétlenül jelenti azt, hogy a CLI lesz a {PREFIX}/bin/php helyre másolva a make install idejére.
A PHP 4.2.0 és PHP 4.2.3 közötti windows-os csomagok a CLI-t php-cli.exe-ként tartalmazták ugyanabban a könyvtárban, mint a CGI php.exe. A PHP 4.3.0-tól kezdődően a windows-os csomag a CLI-t php.exe-ként tartalmazza egy cli nevű könyvtárban, azaz cli/php.exe. A PHP 5-től kezdődően a CLI a főkönyvtárban van és a neve php.exe. A CGI verzió a php-cgi.exe.
A PHP 5-től egy új php-win.exe nevű fájl is található a csomagban. Ez csak annyiban különbözik a CLI verziótól, hogy a kimenetre nem ír ki semmit, így nem jelenít meg konzolt (nem jelenik meg a dos ablak a képernyőn). Ez a viselkedésmód hasonló a php-gtk-éhoz. A configure opciók között az --enable-cli-win32 kell szerepeljen.
Note: Milyen SAPI-m van? Egy shell-be beírva a php -v elárulja hogy a php CGI vagy CLI. Lásd még a php_sapi_name() függvényt valamint a PHP_SAPI konstanst.
Note: A PHP 4.3.2-től egy létrejött egy unix man oldal. Ezt a man php shell-be beírt paranccsal nézheted meg.
Lényegesebb különbségek a CLI SAPI és a többi SAPI között:
-
A CGI SAPI-val ellentétben soha nem ír ki fejléceket.
Habár a CGI SAPI lehetőséget ad a HTTP fejlécek letiltására egy kapcsolóval, de ez nem egyenértékű a CLI SAPI által nyújtott megoldással.
A CLI alapértelmezetten "csendes" (quiet) módban indul, bár a -q és a --no-header kapcsolót megtartották a kompatibilitás érdekében, hogy régebbi CGI szkripteket is problémamentesen lehessen futtatni.
Nem cseréli fel az aktuális könyvtárat az éppen futó szkript könyvtárára. (A -C és a --no-chdir kapcsolót azért megtartották a kompatibilitás érdekében)
Egyszerű, szöveges hibaüzenetek (nincs HTML formázás).
-
Vannak php.ini utasítások, melyeket a CLI SAPI egyszerűen figyelmen kívül hagy, mivel nincs közük a shell környezethez:
Figyelmen kívül hagyott php.ini utasítások Utasítás CLI SAPI default value Magyarázat html_errors FALSE A shellben lehetetlen elolvasni a hibaüzeneteket, ha azok zavaros HTML elemekkel tarkítva száguldanak át a képernyőn. Emiatt ez az utasítás alapértelmezetten FALSE. implicit_flush TRUE Általában azt akarjuk, hogy a print(), echo() és a hasonszőrű függvények mindenképpen írjanak a kimenetre és ne puffereljenek semmit. De használható a output buffering utasítás, ha a kimenet késleltetése vagy manipulálása a cél. max_execution_time 0 (korlátlan) Minden eshetőségre felkészülve a PHP nem korlátozza a shell szkriptek futásidejét. Ez érthető, hiszen míg egy webes szkript általában nagyon gyorsan lefut, addig a shellprogramok nagyon hosszú ideig futhatnak. register_argc_argv TRUE Mivel ez a beállítás TRUE, CLI SAPI-ban mindig rendelkezésedre állnak az argc (az alkalmazásnak átadott argumentumok száma) és az argv (az aktuális argumentumok tömbje) változók.
A PHP 4.3.0-tól a $argc és a $argv PHP változók CLI SAPI használata esetén létrejönnek és feltöltődnek a megfelelő értékekkel. Azelőtt ezen változók létrehozása ugyanúgy működött mint a CGI és MODUL verziókban, ahol a register_globals be kellett legyenek kapcsolva. A $_SERVER vagy a $HTTP_SERVER_VARS tömböt mindig használhatod függetlenül a verziótól és a register_globals beállítástól.
Note: Ezek az utasítások nem adhatók meg a fentiektől különböző értékekkel a konfigurációs php.ini fájlban vagy egyéb saját php.ini-ben (ismert, hogy több php.ini is használható, akár könyvtáranként más). Ez egy korlátozás, mert alapértelmezett értékeik azután aktiválódnak, miután a konfigurációs fájlok lefutottak. Azonban ezek az értékek változhatnak a szkript futása alatt (ami nincs hatással minden említett utasításra, pl. register_argc_argv).
-
Hogy kényelmesebbé tegyék a parancssori programozást, néhány konstanst előre definiáltak:
Specifikus CLI konstansok konstansok Leírás STDIN Egy, már megnyitott stream (folyam) a stdin-re (standard input - bemenet). A stream következőképpen történő megnyitásától a megkímél bennünket: <?php
$stdin = fopen('php://stdin', 'r');
?><?php
$line = trim(fgets(STDIN)); // egy sor olvasása a STDIN-ről
fscanf(STDIN, "%d\n", $number); // szám olvasása a STDIN-ről
?>STDOUT Egy, már megnyitott stream az stdout-ra (standard output - kimenet). A stream következőképpen történő megnyitásától a megkímél bennünket: <?php
$stdout = fopen('php://stdout', 'w');
?>STDERR Egy, már megnyitott stream az stderr-re (ez a hibaüzenetek kiíratásáért felelős). A stream következőképpen történő megnyitásától a megkímél bennünket: <?php
$stderr = fopen('php://stderr', 'w');
?>A fentieknek megfelelően nincs szükség arra, hogy pl. megnyiss egy streamet az stderr-ért, hanem egyszerűen csak használd a konstanst a stream forrás helyett:
php -r 'fwrite(STDERR, "stderr\n");'
-
A CLI SAPI nem cseréli az aktuális könyvtára a futó szkript könyvtárára!
Szemléletes példa erre a CGI SAPI sajátosságra:
<?php
// Ez a mi kis tesztprogramunk amelynek neve: test.php
echo getcwd(), "\n";
?>A CGI verzió használatakor a következőkre számíthatunk:
Ebből tisztán látszik, hogy a PHP lecserélte az aktuális könyvtárat a futtatott szkriptére.$ pwd //Linux/Unix alatt kiírja az aktuális könyvtárat /tmp //az aktuális könyvtár a /tmp $ php -q másik_könyvtár/test.php /tmp/másik_könyvtár
Ugyanez a CLI SAPI-val:
Ez sokkal nagyobb rugalmasságot biztosít a parancssori programok írása során a PHP-ben.$ pwd /tmp $ php -f másik_könyvtár/test.php /tmp
Note: A fenti példában a CGI SAPI ugyanúgy viselkedik, mint a CLI SAPI, ha a -C kapcsolóval indítod a szkriptet a parancssorból.
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] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...] php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...] php [options] -- [args...] -a Run interactively -c <path>|<file> Look for php.ini file in this directory -n No php.ini file will be used -d foo[=bar] Define INI entry foo with value 'bar' -e Generate extended information for debugger/profiler -f <file> Parse <file>. -h This help -i PHP information -l Syntax check only (lint) -m Show compiled in modules -r <code> Run PHP <code> without using script tags <?..?> -B <begin_code> Run PHP <begin_code> before processing input lines -R <code> Run PHP <code> for every input line -F <file> Parse and execute <file> for every input line -E <end_code> Run PHP <end_code> after processing all input lines -H Hide any passed arguments from external tools. -s Display colour syntax highlighted source. -v Version number -w Display source with stripped comments and whitespace. -z <file> Load Zend extension <file>. 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:
-
Hogyan lehet a PHP-vel fájlokat futtatni.
Mindkét módon (vagy 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ó.php my_script.php php -f my_script.php
-
PHP kód futtatása közvetlenül a parancssorból.
Különösen figyelni kell a shell változók helyettesítésére és az idézőjelekre!php -r 'print_r(get_defined_constants());'
Note: 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.
-
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
Mint minden shellprogram, a PHP bináris képes argumentumokat fogadni, viszont az általad írt PHP szkript is. 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, és az utána következő az argumentumokat a PHP 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" }
Azonban 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. Ha megfelelően beállítottad a fájl futtatási jogosultságát (pl. chmod +x test), úgy futtathatod a programodat, mint egy normál shell vagy perl szkriptet:
#!/usr/bin/php
<?php
var_dump($argv);
?>
$ chmod +x test $ ./test -h -- foo array(4) { [0]=> string(6) "./test" [1]=> string(2) "-h" [2]=> string(2) "--" [3]=> string(3) "foo" }
A hosszú opciók a PHP 4.3.3-tól léteznek.
Opció | Hosszú opció | Leírás |
---|---|---|
-a | --interactive |
A PHP-t interaktív módban futtatja. |
-c | --php-ini |
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..:
|
-n | --no-php-ini |
A php.ini teljes figyelmen kívül hagyása. Ez a kapcsoló a PHP 4.3.0 óta létezik. |
-d | --define |
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ő:
Példák (a sorok az olvashatóság érdekében vannak tördelve):
|
-e | --profile-info |
Aktiválja a részletes információs módot, amelyet a debugger/profiler használ. |
-f | --file |
Értelmezi és futtatja az -f kapcsoló után megadott fájlot. Ez a kapcsoló opcionális és el lehet hagyni, pusztán a fájlnév elegendő a fájl futtatásához. |
-h és -? | --help és --usage | 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. |
-i | --info | Ez a parancsori opció meghívja a phpinfo() függvényt és kiírja az eredményét. Ha a PHP rosszul működik, ajánlatos kiadni egy php -i parancsot és figyelmesen elolvasni a hibaüzeneteket a táblázatokban. Készülj fel rá, hogy ha a CGI módot használod, akkor 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.) |
-l | --syntax-check |
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. ;)
|
-m | --modules |
Eme opció használatával a PHP kilistázza a beépített (és betöltött) PHP és Zend modulokat:
|
-r | --run |
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 szintaktikai hibához fog vezetni, ha mégis alkalmazod őket.
|
-B | --process-begin |
Az stdin feldolgozása előtt végrehajtandó PHP kód. PHP 5-től létezik. |
-R | --process-code |
Minden bemeneti sorra végrehajtandó PHP kód. PHP 5-től létezik. Van két speciális változó, amely ebben a módban használható: $argn és $argi. Az $argn azt a sort tartalmazza, amelyet a PHP éppen feldolgoz, az $argi pedig a sornak a sorszámát tartalmazza. |
-F | --process-file |
Minden bemeneti sorra végrehajtandó PHP fájl. PHP 5-től létezik. |
-E | --process-end |
Minden bemeneti sor feldolgozása után végrehajtandó PHP kód. PHP 5-től létezik. Példa a -B, -R és -E opciók használatára: egy projekt sorainak megszámolása.
|
-s | --syntax-highlight és --syntax-highlighting |
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.
|
-v | --version |
Kiírja a PHP, PHP SAPI, és a Zend verziószámát a standard kimenetre, pl:
|
-w | --strip |
Kommentek és felesleges sorközök nélkül listázza ki a kódot.
|
-z | --zend-extension |
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. |
A PHP futtatható állomány segítségével PHP szkripteket webszervertől függetlenül lehet futtatni. Ha egy Unix rendszeren vagy, a PHP szkripted elejére egy speciális sort kell beillesztened, majd az állományt futtathatóvá kell tenned, így a rendszer tudni fogja melyik programmal kell futtatni a szkriptet. Windows-on a .php állományokhoz hozzárendelheted a php.exe programot, vagy készíthetsz egy batch fájlt, amellyel a szkriptet PHP-n keresztül tudod futtatni. A Unix rendszerek miatt beszúrt első sor nem fog problémát okozni Windows-on, így írhatsz platformfüggetlen programot is. Alább található egy példa parancssor PHP program írására.
Example#1 Parancssorból futtatható szkript (script.php)
#!/usr/bin/php
<?php
if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
?>
Ez egy parancssori PHP szkript egy opcióval.
Használat:
<?php echo $argv[0]; ?> <opció>
Az <opció> lehet bármilyen szó, amit
szeretnél kiiratni. --help, -help, -h,
vagy -? opciókra ezt a súgót kapod.
<?php
} else {
echo $argv[1];
}
?>
A fenti szkriptben használtuk a speciális első sort, hogy ezt a fájlt a PHP futtassa. Most a CLI verziót használjuk, így nem lesznek HTTP fejlécek kiírva. Van két változó, amit használhatsz parancssori PHP alkalmazások írásakor: $argc and $argv. Az első megadja az argumentumok számát + 1 (a futó szkript nevét). A második egy tömb, amely az argumentumokat tartalmazza, a szkript nevével kezdődően 0-tól számozva ($argv[0]).
A fenti programban megvizsgáljuk, hogy több vagy kevesebb mint egy argumentum van-e megadva. Ekkor vagy ha az argumentum --help, -help, -h vagy -?, akkor kiíratjuk a súgó üzenetet, a szkriptnevet dinamikusan írjuk ki. Ha más argumentumot kapunk, akkor azt kiírjuk.
Ha a fenti szkriptet Unix-on szeretnéd futtatni, futtathatóvá kell tenned, majd egyszerűen meghívhatod mint például script.php echothis vagy script.php -h. Windows-on készíthetsz egy batch fájlt erre a célra:
Example#2 Batch fájl parancssori PHP szkript futtatására (script.bat)
@c:\php\cli\php.exe script.php %1 %2 %3 %4
Feltételezve, hogy a fenti programot script.php-nek nevezted el, és a php.exe CLI programod a c:\php\cli\php.exe helyen van, ez a batch fájl lefutattja neked a további opciókkal: script.bat echothis vagy script.bat -h.
Lásd még a Readline kiterjesztés dokumentációját, ahol további függvényeket találsz a parancssori PHP alkalmazásaid fejlesztéséhez.