Question

Disons que nous avons une signature de méthode comme

public static function explodeDn($dn, array &$keys = null, array &$vals = null,
    $caseFold = self::ATTR_CASEFOLD_NONE)

nous pouvons facilement appeler la méthode en omettant tous les paramètres après $ dn :

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com');

Nous pouvons également appeler la méthode avec 3 paramètres:

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v);

et avec 4 paramètres:

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v, 
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);

Mais pourquoi est-il impossible d'appeler la méthode avec la combinaison de paramètres suivante, par exemple:

$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, null, 
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);
$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', null, $v);

Quelle est la différence entre transmettre null à la méthode et s'appuyer sur la valeur par défaut? Cette contrainte est-elle écrite dans le manuel? Peut-il être contourné?

Était-ce utile?

La solution

C'est parce que vous ne pouvez pas avoir de référence à null.

Vous pouvez avoir une référence à une variable qui contient null - c'est exactement ce que fait la valeur par défaut. Vous pouvez également indiquer null sous la forme d'une valeur littérale - mais comme vous souhaitez un paramètre out, ce n'est pas possible ici.

Autres conseils

Bien que vous deviez créer une variable factice pour les arguments de référence, si vous souhaitez passer explicitement la valeur NULL, vous n'avez pas à créer cette variable sur une ligne distincte. Vous pouvez utiliser directement une expression d’affectation telle que $ dummy = NULL comme argument de fonction:

function foo (&$ref = NULL) {

    if (is_null($ref)) $ref="bar";
    echo "$ref\n";        
}

foo($dummy = NULL); //this works!

Je viens de le découvrir moi-même, et je suis assez sous le choc o_O!

C’est ce que la documentation PHP dit:

function makecoffee($type = "cappuccino")
{
    return "Making a cup of $type.\n";
}
echo makecoffee(); // returns "Making a cup of cappuccino."
echo makecoffee(null); // returns "Making a cup of ."
echo makecoffee("espresso"); // returns "Making a cup of espresso."

Je me serais attendu à ce que makecoffee (null) renvoie "Préparer une tasse de cappuccino". Une solution que j'ai utilisée consiste à vérifier à l'intérieur de la fonction si l'argument est null:

function makecoffee($type = null)
{
    if (is_null($type)){ 
       $type = "capuccino";
    }
    return "Making a cup of $type.\n";
}

Maintenant, makecoffee (null) renvoie "Préparer une tasse de cappuccino".

(Je réalise que cela ne résout pas vraiment la question de Zend, mais cela pourrait être utile à certains ...)

@ Tomalak

En fait, la valeur par défaut crée une variable sans aucune référence. Ce qui est quelque chose que vous ne pouvez tout simplement pas lancer lorsque vous passez quelque chose.

Ce que je trouve pour illustrer les raisons est l'exemple suivant (que je n'ai pas testé):

function foo (&$ref = NULL) {
  $args = func_get_args();
  echo var_export($ref, TRUE).' - '.var_export($args, TRUE);
}
$bar = NULL;
foo();     // NULL - array()
foo($bar); // NULL - array(0 => NULL)

À mon avis, PHP devrait offrir un moyen de ne PAS transmettre certains paramètres, comme avec
foo ($ p1,,, $ p4); ou une syntaxe similaire au lieu de passer NULL.
Mais ce n’est pas le cas, vous devez donc utiliser des variables nominales.

Juste pour confirmer ce que Tomalak a déclaré ici :

Les travaux suivants:

$k=array();
$v=null;
$dn=Zend_Ldap_Dn::explodeDn('CN=Alice Baker,CN=Users,DC=example,DC=com', $k, $v, 
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER);

Pas sympa - mais l'explication est claire et compréhensible.

Comme @aschmecher l’a souligné dans un commentaire La réponse de @ Szczepan ici , faire func ($ var = null) génère un avis de normes strict.

Une solution

Voici une méthode qui ne génère pas de tels avertissements:

<?php
error_reporting(E_ALL | E_STRICT);

function doIt(&$x = null) {
    if($x !== null) echo "x not null: $x\n";
    $x = 2;
}

function &dummyRef() {
    $dummyRef = null;
    return $dummyRef;
}

doIt(dummyRef());

doIt(dummyRef());

Explication

Au lieu de passer une variable, nous transmettons le résultat d’une fonction renvoyant une référence. Le deuxième appel à doIt (dummy ()) consiste à vérifier que la valeur de référence $ dummy ne persiste pas entre les appels. Cela contraste avec la création explicite d'une variable, dans laquelle il faut se rappeler d'effacer toute valeur accumulée:

$dummyRef = null;
doIt($dummyRef);
doIt($dummyRef); // second call would print 'x not null: 2'

Application

Donc dans l'exemple du PO, ce serait:

$dn = Zend_Ldap_Dn::explodeDn(
    'CN=Alice Baker,CN=Users,DC=example,DC=com',
    $k,
    dummyRef(),
    Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER
);

Considérations supplémentaires

Ce qui me préoccupe peut-être est de savoir si cette méthode crée une fuite de mémoire. Le test suivant montre que ce n'est pas le cas:

<?php
function doItObj(&$x = null) {
    if(gettype($x) !== "object") echo "x not null: $x\n";
    $x = 2;
}

function &dummyObjRef() {
    $dummyObjRef = new StdClass();
    return $dummyObjRef;
}

echo "memory before: " . memory_get_usage(true) .  "\n";

for($i = 0; $i < 1000000; $i++) {
    doItObj(dummyObjRef());
}

echo "memory after: " . memory_get_usage(true) . "\n";

echo "\n$i\n";

Sur mon système (utilisant PHP 5.6.4), les deux appels à memory_get_usage indiquaient ~ 262 Ko.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top