Domanda

Supponiamo di avere una firma del metodo come

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

possiamo facilmente chiamare il metodo omettendo tutti i parametri dopo $ dn :

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

Possiamo anche chiamare il metodo con 3 parametri:

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

e con 4 parametri:

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

Ma perché è impossibile chiamare il metodo con la seguente combinazione di parametri, ad esempio:

$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 è la differenza tra passare null al metodo e fare affidamento sul valore predefinito? Questo vincolo è scritto nel manuale? Può essere eluso?

È stato utile?

Soluzione

È perché non puoi avere un riferimento a null.

Puoi avere un riferimento a una variabile che contiene null - questo è esattamente ciò che fa il valore predefinito. Oppure puoi passare a null come valore letterale, ma poiché vuoi un parametro out questo non è possibile qui.

Altri suggerimenti

Sebbene sia necessario creare una variabile fittizia per argomenti by-ref se si desidera passare NULL in modo esplicito, non è necessario creare quella variabile su una riga separata. È possibile utilizzare un'espressione di assegnazione come $ dummy = NULL direttamente come argomento della funzione:

function foo (&$ref = NULL) {

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

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

L'ho appena scoperto da solo e sono piuttosto scioccato o_O!

Questo è ciò che Documentazione PHP dice:

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

Mi sarei aspettato che makecoffee (null) restituisse " Fare una tazza di cappuccino. " ;. Una soluzione che ho usato è quella di verificare all'interno della funzione se l'argomento è null:

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

Ora makecoffee (null) restituisce " Preparare una tazza di cappuccino. "

(Mi rendo conto che in realtà questo non risolve la domanda relativa a Zend, ma potrebbe essere utile per alcuni ...)

@ Tomalak

In realtà, il valore predefinito crea una variabile senza alcun riferimento. Che è qualcosa che semplicemente non puoi dare il via quando passi qualcosa.

Quello che trovo per illustrare i motivi è il seguente esempio (che non ho testato):

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)

Secondo me, PHP dovrebbe offrire un modo per NON passare determinati parametri, come con
foo ($ p1,, $ p4); o sintassi simile invece di passare NULL.
Ma non è così, quindi devi usare variabili fittizie.

Solo per confermare ciò che Tomalak ha dichiarato qui :

Le seguenti opere:

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

Non è carino, ma la spiegazione è chiara e comprensibile.

Come ha sottolineato @aschmecher in un commento su @ La risposta di Szczepan qui , facendo func ($ var = null) genera un severo avviso sugli standard.

Una soluzione

Ecco un metodo che non genera tali avvisi:

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

Spiegazione

Al posto del passaggio in una variabile, passiamo al risultato di una funzione che restituisce un riferimento. La seconda chiamata a doIt (dummy ()) è verificare che il valore di riferimento $ dummy non sia persistente tra le chiamate. Ciò contrasta con la creazione esplicita di una variabile, in cui è necessario ricordare di cancellare qualsiasi valore accumulato:

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

Applicazioni

Quindi nell'esempio del PO sarebbe:

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

Ulteriori considerazioni

Una cosa di cui potrei preoccuparmi è se questo metodo crea una perdita di memoria. Il seguente test mostra che non funziona:

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

Sul mio sistema (usando PHP 5.6.4), entrambe le chiamate a memory_get_usage hanno mostrato ~ 262 KB.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top