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.6 Cas des arguments passés par référence

Si votre fonction accepte des arguments passés par référence, que vous souhaitez modifier, vous devez prendre certaines précautions.

Ce que nous n'avons toujours pas précisé, et que dans les circonstances actuelles, vous n'avez pas le droit de modifier les enveloppe zval désignant les paramètres passés à votre fonction. Bien sûr, vous pouvez modifier n'importe quelle enveloppe zval que vous créez dans votre fonction, mais vous ne devez changer aucune zval qui fasse référence aux données internes de Zend.

Nous avons uniquement parlé des fonctions *_ex, jusqu'à maintenant. Nous avez peut être remarqué que les fonctions que nous avons utilisé s'appelait zend_get_parameters_ex au lieu de zend_get_parameters, convert_to_long_ex au lieu de convert_to_long, etc... Les fonctions *_ex forment les nouvelles API "étendues" de Zend. Elles apportent une légère amélioration en terme de vitesse sur la version précédente, mais, en échange, ne sont conçues que pour fournir des accès en lecture seule.

Comme Zend fonctionne en interne avec des références, les différentes variables peuvent faire référence à la même valeur. L'accès en écriture à une enveloppe zval impose que l'enveloppe contiennent une valeur isolée, c'est à dire qu'elle ne doit pas être référencés par une autre enveloppe. Si une enveloppe zval était référencée par une autre envelope, si vous modifiez la valeur de la première, vous modifiez aussi celle de la seconde (car elles pointent simplement vers la valeur modifiée, et par conséquent, modifie leur propre valeur en même temps).

zend_get_parameters_ex ne prend pas en compte cette situation, mais retourne simplement un pointeur sur l'enveloppe désirée, que cette dernière soit une référence ou pas. Sa version dans l'API traditionnelle zend_get_parameters, vérifie immédiatement les valeurs référencées. Si elle trouve une référence, elle crée une nouvelle enveloppe zval isolée; copie les données référencées dans le nouvel espace créé; puis retourne un pointeur sur cette nouvelle valeur isolée.

Cette action est appelée séparation de zval  (zval separation , ou encore pval separation). Parceque les API *_ex n'effectue pas de séparation de zval, elle est considérablement plus rapide, mais n'autorise pas l'accès en écriture.

Pour modifier des paramètres, un accès en écriture est nécessaire. Zend traite cette situation d'une manière spéaciale : A chaque fois qu'un paramètre est passé à une fonction, et qu'il est passé par référence, Zend effectue une séparation de zval. Cela signifie que toutes les fois où vous appelér une fonction en PHP, en passant des arguments par référence, Zend s'assure automatiquement que $parameter est passé comme une valeur isolée, avec la possibilité d'y accéder en écriture.


my_function(&$parameter);

Mais ce n'est pas  le cas avec les paramètres normaux. Tous les paramètres qui ne sont pas passés par références sont dans un état de lecture seule.

Cela vous impose de devoir vous assurer que vous travaillez avec une référence : sinon, vous risquez de produire des résultats indésirables. Pour vérifier si un paramètre est passé par référence, vous pouvez utiliser la macro PZVAL_IS_REF. Cette macro accepte un valeur de type zval*, et vérifie si c'est une référence. Des exemples sont disponibles dans <>.

Test pour savoir si un paramètre est passé par référence

zval *parameter;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE)
    return;
/* vérifie si le paramètre est passé par référence */
if (!PZVAL_IS_REF(*parameter)) {
{
    zend_error(E_WARNING, "Parameter wasn't passed by reference");
    RETURN_NULL();
}
/* modifie le paramètre */
ZVAL_LONG(*parameter, 10);

Chapitre précédentChapitre suivantAccueil nexen.net