SommaireTelecharger la documentationChapitre suivantChapitre precedent  

  .: News :.: Edito :.: Scripts :.: Forum :.: Erreurs :.: Jobs :. 
 
Sommaire

Gestion des arguments

Compter le nombre d'arguments
Lecture des arguments
L'ancienne technique de lecture des arguments (obsolète)
Cas des nombres variables de paramètres et des arguments optionnels
Accéder aux arguments
Cas des arguments passés par référence
Assurer la protection en écriture des autres paramètres

7.10.2 Lecture des arguments

Note
Nouvelles API de traitement des paramètres

Ce chapitre documente la nouvelle API de traitement des arguments, introduite par Andrei Zmievski. Elle a été mise en place entre PHP 4.0.6 et 4.1.0 .

Analyser les paramètres est une opération très fréquente, et devient rapidement laborieuse. Il serait aussi bon d'avoir des messages de vérifications et d'erreurs unifiés. Depuis PHP 4.1.0, il y a un moyen de faire cela en utilisant la nouvelle API. Elle simplifie énormément le processus de reception des paramètres. Elle n'est toute fois pas utilisable avec les fonctions qui attendent un nombre de paramètre variable. Mais comme la majorité des fonctions demandent un nombre fixe de paramètres, cette API est vivement recommandée.

Le prototype de la fonction de traitement des arguments ressemble à ceci :


int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
Le premier argument de cette fonction est supposé être le nombre réel d'arguments passé à votre fonction, ce qui fait que ZEND_NUM_ARGS() peut être utilisé ici. Le second paramètre doit toujours être la macro TSRMLS_CC. Le troisième argument est une chaîne qui spécifie le nombre et le type d'arguments demandé, similaire au format utilisé avec la fonction printf(). Et finalement, le reste des arguments sont des pointeurs sur les variables qui vont recevoir les valeurs des paramètres.

zend_parse_parameters effectue aussi le transtypage à chaque fois que cela est possible, ce qui vous permet de recevoir les valeurs au format que vous demandez. N'importe quel type de scalaire peut être convertis en un auter, mais les conversions entre les types complexes (tableaux, objet et ressources) et les types scalaires sont interdits.

Si les paramètres ont pu être obtenu sans problème, et qu'il n'y a pas eu d'erreur durant les conversions, la fonction retournera SUCCESS, sinon, elle retournera FAILURE. La fonction affichera un message d'erreur informatif, si le nombre d'argument reçu n'est pas celui demandé, ou si les conversions ont échouées.

Voci quelques exemples de message d'erreur :

     Warning - ini_get_all() requires at most 1 parameter, 2 given
     Warning - wddx_deserialize() expects parameter 1 to be string, array given
    
Bien sûr, chaque message d'erreur est accompagné du nom du fichier et du numéro de ligne ou l'erreur intervient.

Voici la liste complète des spécificateurs de type :

  • l - long

  • d - double

  • s - chaîne de caractères (avec le caractère null éventuellement) et sa longueur

  • b - booléen

  • r - ressource, stockée dans un zval*

  • a - tableau, stocké dans un zval*

  • o - objet (de classe libre), stocké dans un zval*

  • O - objet (de classe spécifiée par class entry), stockée dans un zval*

  • z - le zval* lui-même

Les caractères suivants ont aussi une signification dans la chaîne de spécification :
  • | - indique que les paramètres suivants sont optionnels. Les variables de stockage de ces paramètres doivent être initialisés à leur valeur de défaut, car elles ne seront pas touchées par l'API si ces paramètres ont été omis.

  • / - L'API va appeler la fonction separate_zval_if_not_ref pour le paramètre suivant, pour fournir une copie du paramètre, à moins que cela ne soit une référence.

  • ! - le paramètre qui suit peut être du type spécifié, ou bien NULL (uniquement valable pour les types a, o, O, r, et z). Si la valeur NULL est passée par l'utilisateur, le pointeur de stockage sera mis à NULL.

La meilleure façon d'illustrer l'utilisation de cette fonction est de lire ces exemples :


/* Lit un long, une chaîne et sa longueur, et un zval. */
long l;
char *s;
int s_len;
zval *param;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
                          "lsz", &l, &s, &s_len, &param) == FAILURE) {
    return;
}
/* Lit un objet de classe spécifiée par my_ce, et un double optionnel*/
zval *obj;
double d = 0.5;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
                          "O|d", &obj, my_ce, &d) == FAILURE) {
    return;
}
/* Lit un objet ou NULL, et un tableau.
   Si null est passé comme objet, obj sera mis à NULL. */
zval *obj;
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!a", &obj, &arr) == FAILURE) {
    return;
}
/* Lit un tableau séparé. */
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &arr) == FAILURE) {
    return;
}
/* Lit seulement les trois premiers paramètres (pratique pour les fonctions varargs). */
zval *z;
zend_bool b;
zval *r;
if (zend_parse_parameters(3, "zbr!", &z, &b, &r) == FAILURE) {
    return;
}

Notez que dans le dernier exempple, nous passons 3 comme nombre d'arguments reçus, à la place de zend_num_args. Cela nous permet d'utiliser cette API pour traiter les trois permiers arguements. Bien entendu, si votre fonction accepte un nombre variable de paramètres, vous devrez utiliser la fonction zend_get_parameters_array_ex pour les obtenir et les traiter par vous même.

L'API a aussi une version étendue qui supporte l'utilisation d'autres options dans la chaîne de spécifications.


int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);

La seule option que vous pouvez passer actuellement est ZEND_PARSE_PARAMS_QUIET, qui indique que la fonction ne doit pas afficher d'erreur durant son exécution. C'est pratique pour les fonctions qui attendent plusieurs jeux d'arguments complétement différents. Vous aurez alors la charge d'afficher vous même les erreurs.

Par exemple, voici comment vous devez utiliser l'API si vous attendez soit trois longs, ou trois chaînes :


long l1, l2, l3;
char *s;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
                             ZEND_NUM_ARGS() TSRMLS_CC,
                             "lll", &l1, &l2, &l3) == SUCCESS) {
    /* traite les longs */
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
                                    ZEND_NUM_ARGS(), "s", &s, &s_len) == SUCCESS) {
    /*  traite les chaînes */
} else {
    php_error(E_WARNING, "%s() takes either three long values or a string as argument",
              get_active_function_name(TSRMLS_C));
    return;
}

Avec toutes les méthodes de gestion des paramètres présentées ci-dessus, vous devriez avoir une bonne visibilité sur ce processus. Pour encore plus d'exemples, regardez dans le code source des extensions qui sont distribuées avec PHP : elles illustreront toutes les situations possibles et imaginables.


Chapitre précédentChapitre suivantAccueil nexen.net