Chapitre 23. Utiliser PHP en ligne de commande

Depuis la version 4.3, PHP supporte un nouveau type de SAPI (Server Application Programming Interface, c'est à dire Interface de Programmation d'Applications Serveur) appelé CLI, ce qui signifie Command Line Interface et se traduit par Interface de Ligne de Commande. Comme son nom l'indique, ce type SAPI cible les applications shell (ou desktop), écrites en PHP. Il y a pas mal de différences enter le type CLI SAPI et les autres SAPI, qui sont expliqués dans ce chapitre.

Le CLI SAPI a été publié puor la première fois avec la version PHP 4.2.0, mais il est resté expérimental, et doit être explicitement activé avec la commande --enable-cli, lorsque vous exécutez le script ./configure. Depuis PHP 4.3.0, le CLI SAPI n'est plus expérimental, et est donc toujours compilé et installé comme binaire PHP (appelé aussi php.exe sous Windows).

Les différences les plus notables entre le CLI SAPI et les SAPI sont :

La liste des options de ligne de commande fournies par PHP est disponible en exécutant PHP avec l'option -h :
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

Le CLI SAPI dispose de trois moyens pour lire le code du script PHP que vous voulez exécuter :

  1. Indiquer à PHP d'exécuter un fichier :

    php mon_script.php
    
    php -f mon_script.php
    Les deux méthodes (en utilisant -f ou pas) exécute le script contenu dans le fichier mon_script.php. Vous pouvez choisir n'importe quel fichier, et ces fichiers ne sont pas tenus d'utiliser l'extension .php. N'importe quelle extension peut faire l'affaire.

  2. Donner du code PHP à exécuter directement en ligne de commande.

    php -r 'print_r(get_defined_constants());'
    Une attention particulière doit alors être apportée aux variables d'environnement, qui seront remplacées, et aux guillements, qui ont des significations spéciales en ligne de commande.

    Note : Lisez l'exemple attentivement, il n'y a ni balise d'ouverture, ni balise de fermeture! L'option -r fonctionne sans ces balises, et les ajouter conduira alors à une erreur d'analyse.

  3. Donner du code PHP dans l'entrée standard (stdin).

    Cela donne la possibilité de créer dynamiquement du code PHP, puis de le fournir à PHP, et enfin, de le traiter à nouveau en shell. Voici un exemple fictif :
    $ some_application | some_filter | php | sort -u >final_output.txt

Il n'est pas possible de combiner ces trois modes d'exécution.

Comme toute application shell, l'exécutable PHP accepte des arguments, et votre script peut aussi les recevoirs. Le nombre d'arguments n'est pas limité par PHP, mais par le shell, qui a une limite en terme de nombre de caractères qui peuvent être passés. Généralement, vous n'atteidrez pas cette limite, mais cela reste possible. Les arguments passés au script seront transmis via la variable tableau $argv. L,index zéro contiendra toujours le nom du script appelé. Si le code a été fourni en ligne de commande, ou via stdin, ce premier élément vaudra -. L'autre variable globale fournie est $argc qui contient le nombre d'éléments dans le tableau $argv : ce nombre est différent du nombre d'arguments passés au script.

Tant que les arguments que vous passez à votre script ne commencent pas par le caractère -, il n'y a rien de spécial à surveiller. Si vous passez des arguments à voter script qui commencent par -, cela posera des problèmes car PHP va penser qu'il doit les interpréter. Pour éviter cela, utilisez le séparateur --. Après cet argument, tous les arguments suivants seront passés à votre script sans être modifié ou analysé par PHP.

# Cela ne va pas ex&eacute;cuter le code, mais afficher l'aide de PHP
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]

# Cela va passer l'argument '-h' &agrave; votre script, et &eacute;viter que PHP ne le traite
$ php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}

Cependant, il y a une autre méthode pour utiliser PHP en script shell. Vous pouvez aussi utiliser la ligne #!/usr/bin/php en tout début de votre script, suivi de code PHP compris entre balise ouvrantes/fermantes. Vous pouvez aussi ajouter après #!/usr/bin/php les options nécessaires. Vous pouvez aussi le faire en ligne de commande. De cette manière, le script peut être exécuté comme un script shell habituel :
#!/usr/bin/php
<?php
    var_dump($argv);
?>
En supposant que ce fichier s'appelletest, dans le dossier courant, nous pouvons alors faire ceci :
$ chmod 755 test
$ ./test -h -- foo
array(4) {
  [0]=>
  string(6) "./test"
  [1]=>
  string(2) "-h"
  [2]=>
  string(2) "--"
  [3]=>
  string(3) "foo"
}
Comme vous le voyez, aucune précaution n'est nécessaire pour passer des paramètres qui commencent par - à votre script.

Tableau 23-3. Options de ligne de commande

OptionDescription
-s

Affiche le code avec la colorisation syntaxique.

Cette option utilise le mécanisme interne pour analyser le fichier, et produire une version colorisée du code source, au format HTML. Notez que cette option ne fait que générer un bloc HTML, sans les entêtes. <code> [...] </code>

Note : Cette option ne fonctionne pas avec l'option -r.

-w

Affiche la source sans les commentaires et les espaces.

Note : Cette option ne fonctionne pas avec l'option -r.

-f

Analyse et exécute le fichier donné après l'option -f. Cette optione est optionnelle, et peut être omise. Le seul nom du fichier est suffisant.

-v

Affiche les versions de PHP, PHP SAPI, et Zend sur le terminal. Par exemple :
$ 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

Avec cette option, vous pouvez spécifier le nom du dossier dans lequel PHP va recherche le fichier php.ini, ou encore vous pouvez spécifier un fichier de configuration directement (qui n'a pas obligatoirement à être appelé php.ini) :
$ php -c /custom/directory/ mon_script.php

$ php -c /custom/directory/custom-file.ini mon_script.php

-a

Exécute PHP de manière interactive.

-d

Cette option permet de modifier n'importe quelle directive de configuration du fichier php.ini. La syntaxe est :
-d configuration_directive[=value]

Exemples:
# L'omission de la valeur conduit &agrave; donner la valeur de "1"
$ php -d max_execution_time -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"

# Passer une valeur vide conduit &agrave; donner la valeur de ""
php -d max_execution_time= -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""

# La directive de configuration sera n'importe quelle valeur pass&eacute;e apr&egrave;s le caract&egrave;re '='
$  php -d max_execution_time=20 -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$  php -d max_execution_time=doesntmakesense -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "doesntmakesense"

-e

Génére des informations étendues pour le profilage et le débogage.

-z

Charge une extension Zend. Si seulement un fichier est fourni, PHP essaie de charger cette extension dans le dossier courant par défaut des librairie sur votre système (généralement spécifié avec /etc/ld.so.conf sous Linux). Passer un nom de fichier avec le chemin complet fera que PHP utilisera ce fichier, sans recherche dans les dossiers classiques. Un chemin de dossier relatif indiquera à PHP qu'il doit chercher uniquement les extensions dans ce dossier.

-l

Cette option permet de faire une vérification syntaxique sur le code PHP fourni. En cas de réussite, le message No syntax errors detected in <filename> (Aucune d'erreur de syntaxe n'ont été détectées dans <nom_de_fichier> est affiché sur la sortie standard, et le script shell retourne 0. En cas d'erreur, le message Errors parsing <filename> (Erreurs d'analyse dans le fichier <filename>) est affiché, en plus des messages d'erreurs détectés par l'analyseur lui même. Le script shell retourne le code 255.

Cette option ne détecte pas les erreurs fatales (comme par exemple les fonctions non définies). Utilisez -f si vous voulez tester aussi ces erreurs.

Note : Cette option ne fonctionne pas avec l'option -r.

-m

Cette option liste les extensions PHP et Zend compilées et chargées :
$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

-i Cette option appelle la fonction phpinfo(), et affiche le résultat. Si PHP ne fonctionne pas correctement, il est recommandé d'utiliser la commande php -i et de voir si il n'y a pas d'erreurs affichées avant ou après la table d'information. N'oubliez pas que le résutltat de cette option est au format HTML, et donc grand et illisible directement.
-r

Cette option permet l'exécution de PHP directement dans la ligne de commande. Les balises de PHP (<?php et ?>) ne sont pas demandées, et coauseront une erreur d'analyse.

Note : De l'attention doit être portée lors de l'utilisation de cette option de PHP, pour qu'il n'y ait pas de collision avec les substitutions de variables en lignes de commande, réalisées par le shell.

Exemple conduisant à une erreur d'analyse :
$ php -r "$foo = get_defined_constants();"
Command line code(1) : Parse error - parse error, unexpected '='
Le problème ici est que le shell (sh/bash) effectue une substitution de variables, grâce aux guillemets doubles ". puisque la variable $foo n'est probablement pas définie dans le shell, elle est remplacée par rien, ce qui fait que le code passé à PHP pour l'exécution est :
$ php -r " = get_defined_constants();"
La solution de ce problème est d'utiliser les guillemets simples '. Les variables de ces chaînes ne seront pas substituées par leurs valeurs par le shell.
$ 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"]=>
  [...]
Si vous utilisez un shell différent de sh/bash, vous pouvez rencontrer d'autres problèmes. N'hésitez pas à ouvrir un rapport de bugs, ou d'envoyer un mail à phpdoc@lists.php.net. Il est toujours très facile d'avoir des problèmes lorsque vous essayez d'inclure des variables shell dans le code, ou d'utiliser les anti-slash pour l'échappement. Vous aurez été prévenu.

-h Avec cette option, vous pouvez obtenir des informations sur la liste des options supporté par votre PHP, avec des explications succintes.

L'exécutable PHP peut être utilisé pour exécuter des scripts indépendants du serveur web. Si vous êtes sur un système Unix, il est recommandé d'ajouter la ligne de configuration en début de scripts, de le rendre exécutable de manière à ce que le système sache quel programme doit exécuter le script. Sous Windows, vous pouvez associer l'exécutable php.exe avec le double-clic sur les fichiers d'extension .php, ou bien vous pouvez faire un fichier batch pour exécuter le script grâce à PHP. La première ligne utilisée dans le monde Unix ne perturbera pas PHP sous Windows, ce qui rend les scripts facilements portables. Un exemple complet est disponible ci-dessous :

Exemple 23-1. Script prévu pour être exécuté en ligne de commande (script.php)

#!/usr/bin/php
<?php

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

C'est une ligne de commande &agrave; une option.

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

  <option> peut &ecirc;tre un mot que vous souhaitez afficher.
  Avec les options --help, -help, -h,
  et -?, vous obtiendrez cette aide.
  
<?php
} else {
    echo $argv[1];
}
?>

Dans le script ci-dessus, nous utilisons la première ligne pour indiquer que le fichier doit être exécuté par PHP. Nous travaillons avec une version CLI, donc il n'y a pas d'entêtes HTTP qui soient affichés. Il y a deux variables que vous pouvez utiliser avec les applications de ligne de commande : $argc et $argv. La première est le nombre d'arguments plus un (le nom du script qui est exécuté). La seconde est un tableau contenant les arguments, commençant avec le nom du script en élément 0 ($argv[0]).

Dans notre exemple, nous avnos vérifié qu'il y a plus ou moins d'un argument. De plus, si cet argument est --help, -help, -h ou -?, nous avons affiché un message d'aide, ainsi que le nom du script. Nous nous recevons un autre argument, cet argument est affiché dans le terminal.

Pour exécuter le script ci-dessus sous Unix, vous devez le rendre exécuétable, puis l'appeler avec une commande comme : script.php echothis ou script.php -h. Sous Windows, vous pouvez faire un fichier batch pour cela :

Exemple 23-2. Fichier batch pour exécuter un script PHP en ligne de commande (script.bat)

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

Si vous avez nommé le programme ci-dessus script.php, et que vous avez votre exécutable php.exe situé à c:\php\php.exe, ce fichier batch l'exécutera avec les options que vous lui passez : script.bat echothis ou script.bat -h.

Voir aussi l'extension Readline, qui dispose de nombreuses fonctions pour améliorer la convivialité de vos applications en ligne de commande.