PHP kézikönyv
Előző |  | Következő

# 43. 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:

- 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, de a -q 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 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:

  Táblázat 43-1. 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 pár másodperc alatt lefut, addig a shellprogramok nagyon hosszú ideig futhatnak.
  register_argc_argv | `TRUE` | A globális PHP változók $argc (a változók számát adja át a szkriptnek) és a $argv (az aktuális változók tömbje) elválaszthatatlanok a parancssori programok futásától és mindig feltöltődnek a megfelelő értékpárokkal, amikor használod a CLI SAPI-t.

  > Megjegyzés: 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:

  Táblázat 43-2. Specifikus CLI konstansok

  konstansok | Leírás
  --- | ---

  `STDIN`

  Egy, már megnyitott streamet (folyamatot) az stdin-re (standard input - bemenet) küld. A stream megnyitásától a következőképpen kímél meg bennünket:

  `$stdin = fopen('php://stdin', 'r');`

  `STDOUT`

  Egy, már megnyitott streamet az stdout-ra (standard output - kimenet) küld. Ez a stream megnyitásától a következőképpen kímél meg bennünket:

  `$stdout = fopen('php://stdout', 'w');`

  `STDERR`

  Egy, már megnyitott streamet az stdout-ra küld (Ez a hibaüzenetek kiíratásáért felelős.) A stream megnyitásától a következőképpen kímél meg bennünket:

  `$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");'`

  Ezeket a streameket nem kell külön lezárni, automatikusan megteszi ezt a PHP.

- 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 ;) és az aktuális könyvtárat írja ki, amiben éppen "tartózkodunk". Neve: test.php */ echo getcwd(), "\n"; ?>`

  A CGI verzió használatakor a következőkre számíthatunk:

      $ pwd  //Linux/Unix alatt kiírja az aktuális könyvtárat
      /tmp   //az aktuális könyvtár a /tmp

      $ php-cgi -f másik_könyvtár/test.php
      /tmp/másik_könyvtár

  Ebből tisztán látszik, hogy a PHP lecserélte az aktuális könyvtárat a futtatott szkriptére.

  Ugyanez a CLI SAPI-val:

      $ pwd
      /tmp

      $ php -f másik_könyvtár/test.php
      /tmp

  Ez sokkal nagyobb rugalmasságot biztosít a parancssori programok írása során a PHP-ben.

  > Megjegyzés: 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] [-- 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 43-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 43-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 43-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.

Előző | Tartalom | Következő
Functions restricted/disabled by safe mode | Fel | Függvény referencia