Pergunta

Vamos dizer que temos uma assinatura do método como

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

podemos facilmente chamar o método omitindo todos os parâmetros após $dn:

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

Também pode chamar o método com 3 parâmetros:

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

e com 4 parâmetros:

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

Mas por que é impossível para chamar o método com a seguinte combinação de parâmetros, por exemplo:

$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);

Qual é a diferença entre passando null ao método e contando com o valor padrão? É essa restrição escrito no manual? ele pode ser contornado?

Foi útil?

Solução

É porque você não pode ter uma referência a null.

Você pode ter uma referência a uma variável que contém nulo - que é exatamente o que o valor padrão faz. Ou você pode passar em null como um valor literal -. Mas desde que você quer um parâmetro de saída não é possível aqui

Outras dicas

Enquanto você deve criar uma variável dummy para os argumentos por-ref se você quer passar NULL explicitamente, você não tem que criar essa variável em uma linha separada. Você pode usar uma expressão de atribuição como $ manequim = NULL diretamente como um argumento da função:

function foo (&$ref = NULL) {

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

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

Eu só descobri isso mesmo, e eu sou muito em choque o_O!

Este é o que o PHP documentação diz:

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."

Eu teria esperado makecoffee(null) voltar "Fazendo uma xícara de cappuccino.". Uma solução alternativa que tenho usado é verificar dentro da função se o argumento for nulo:

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

Agora makecoffee(null) retorna "Fazendo uma xícara de cappuccino."

(Sei que isso não realmente resolver a questão Zend-relacionado, mas pode ser útil para alguns ...)

@ Tomalak

Na verdade, o valor padrão cria uma variável sem qualquer referência envolvidos. Que é algo que você simplesmente não pode começar quando você passar algo.

O que eu acho para ilustrar as razões é o seguinte exemplo (que eu não fiz teste):

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)

Na minha opinião, PHP deve oferecer uma maneira de não passar determinados parâmetros, como com
foo($p1, , , $p4); ou sintaxe semelhante em vez de passar NULL.
Mas isso não acontecer, então você tem que usar variáveis ??binárias.

apenas para confirmar o que Tomalak declarou aqui :

As seguintes obras:

$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);

Não agradável -. Mas a explicação é clara e compreensível

Como @aschmecher apontadas em um comentário sobre resposta @ de Szczepan aqui , fazendo func($var = null) gera um aviso padrões rigorosos.

Uma solução

Aqui está um método que não gera quaisquer avisos:

<?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());

Explicação

No lugar de passar em uma variável, passamos no resultado de uma função que retorna uma referência. A segunda chamada para doIt(dummy()) é verificar se o valor $dummy referência não persiste entre as chamadas. Isto contrasta com a criação de uma variável explicitamente, onde é preciso lembrar-se de limpar qualquer valor acumulado:

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

Aplicação

Assim, no exemplo do OP, seria:

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

Considerações adicionais

Uma coisa que eu poderia se preocupar é se esse método cria um vazamento de memória. As seguintes mostras de teste que ele faz não:

<?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";

No meu sistema (usando PHP 5.6.4), ambas as chamadas para memory_get_usage mostrou ~ 262 KB.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top