I riferimenti in PHP sono il mezzo per accedere ad uno stesso contenuto di variabile utilizzando diversi nomi. Non si sta parlando di puntatori come in C; per esempio, non si può effettuare aritmetica dei puntatori, perché non sono reali indirizzi di memoria, e così via. Vedere per ulteriori informazioni. Al contrario, sono alias nella tabella dei simboli. Si noti che in PHP, il nome delle variabili e il loro contenuto sono cose diverse, uno stesso contenuto infatti può avere nomi diversi. L'analogia più prossima è quella con i nomi dei file e i file stessi in Unix - i nomi delle variabili sono come directory, mentre il contenuto delle variabili è il file stesso. I riferimenti possono essere pensati come hardlink del filesystem Unix.

Esistono tre operazioni principali effettuate attraverso i riferimenti: assegnare per riferimento, passare per riferimento, e restituzione per riferimento. Questa sezione darà un'introduzione a queste operazioni, con collegamenti per ulteriori informazioni.

Assegnazione per Riferimento

Attraverso questa prima operazione, i riferimenti PHP permettono di far sì che due variabili facciano riferimento allo stesso contenuto. Questo significa, che scrivendo: <?php $a =& $b; ?> $a e $b puntano allo stesso contenuto. $a e $b sono completamente uguali, ma $a non è un puntatore a $b o vice versa, $a e $b puntano semplicemente nello stesso posto.

Nota: Se si assegna, si passa o si restituisce per riferimento una variabile non definita, questa verrà creata. Uso dei riferimenti con variabili non definite <?php function foo(&$var) { } foo($a); // $a is "created" and assigned to null $b = array(); foo($b['b']); var_dump(array_key_exists('b', $b)); // bool(true) $c = new StdClass; foo($c->d); var_dump(property_exists($c, 'd')); // bool(true) ?>

La stessa sintassi può essere usata con funzioni che restituiscono riferimenti, e con l'operatore new (a partire da PHP 4.0.4 e prima di PHP 5.0.0): <?php $foo =& find_var($bar); ?> Da PHP 5, new restituisce automaticamente un riferimento, quindi usare =Amp in questo contesto è deprecato e produce un messaggio E_DEPRECATED in PHP 5.3 e successivi, e un messaggio E_STRICT nelle versioni precedenti. (Tecnicamente, la differenza consiste nel fatto che, in PHP 5, le variabili object, come pure le risorse, sono semplici puntatori ai veri dati dell'oggetto, quindi questi riferimenti a oggetto non sono "riferimenti" nel senso usato in precedenza (alias). Per maggiori informazioni, vedere Oggetti e riferimenti.

Attenzione: Se si assegna un riferimento ad una varibile dichiarata global dall'interno di una funzione, il riferimento sarà visibile solo all'interno della funzione stessa. Si può evitare tutto ciò utilizzando la matrice $GLOBALS. Riferimenti di varibiali globali all'interno di una funzione <?php $var1 = "Example variable"; $var2 = ""; function global_references($use_globals) { global $var1, $var2; if (!$use_globals) { $var2 =& $var1; // visible only inside the function } else { $GLOBALS["var2"] =& $var1; // visible also in global context } } global_references(false); echo "var2 is set to '$var2'\n"; // var2 is set to '' global_references(true); echo "var2 is set to '$var2'\n"; // var2 is set to 'Example variable' ?> Si pensi a global $var; come ad una scorciatoia per $var =Amp $GLOBALS['var'];. Quindi assegnando altri riferimenti a $var si cambia soltanto il riferimento della variabile locale.
Nota: Se si assegna un valore ad una variabile con riferimenti in una istruzione Foreach, anche la variabile a cui si fa riferimento sarà modificata. Riferimenti e istruzione foreach <?php $ref = 0; $row =& $ref; foreach (array(1, 2, 3) as $row) { // esegue qualcosa } echo $ref; // 3 - ultimo elemento dell'array <?

Anche se non sono esattamente un'assegnazione per riferimento, le espressioni create con il costrutto array() si possono comportare come tali anteponendo Amp all'elemento da aggiungere. Esempio: <?php $a = 1; $b = array(2, 3); $arr = array(&$a, &$b[0], &$b[1]); $arr[0]++; $arr[1]++; $arr[2]++; /* $a == 2, $b == array(3, 4); */ ?>

Si noti che i riferimenti all'interno degli array sono potenzialmente pericolosi. Un'assegnazione normale (non per riferimento) di un riferimento nella parte destra dell'espressione non treasforma in riferimento la variabile nella parte sinistra, ma i riferimenti all'interno degli array sono comunque conservati in questo tipo di assegnazioni. Questo si applica anche alle chiamate a funzione dove l'array è passato per valore. Esempio: <?php /* Assegnazione di variabili scalari */ $a = 1; $b =& $a; $c = $b; $c = 7; //$c non è un riferimento; nessun cambiamento in $a o $b /* Assegnazione di variabili array */ $arr = array(1); $a =& $arr[0]; //$a e $arr[0] sono nello stesso insieme di riferimento $arr2 = $arr; //non è un'assegnazione per riferimento! $arr2[0]++; /* $a == 2, $arr == array(2) */ /* Il contenuto di $arr è modificato anche se non è un riferimento! */ ?> In altre parole, da un punto di vista dei riferimenti, il comportamento degli array è definito elemento per elemento; il comportamento di ogni singolo elemento è indipendente dallo stato di riferimento dell'array che lo contiene.

Passaggio per Riferimento

Il secondo utilizzo del riferimento è il passaggio di una variabile per riferimento. Questo si fa dichiarando una variabile locale di una funzione e una variabile nell'ambito della chiamata del riferimento con lo stesso contenuto. Esempio: <?php function foo(&$var) { $var++; } $a=5; foo($a); ?> $a assume il valore 6. Questo accade perché nella funzione foo, la variabile $var si riferisce allo stesso contenuto di $a. Si vedano le spiegazioni più dettagliate per passaggio per riferimento.

Restituzione per Riferimento

Il terzo utilizzo del riferimento è il ritorno per riferimento.

Come detto prima, i riferimenti non sono puntatori. Questo significa, che il seguente costrutto non fà quello che ci si aspetterebbe: <?php function foo(&$var) { $var =& $GLOBALS["baz"]; } foo($bar); ?>

Nell'esempio $var in foo viene scambiato con $bar nella chiamata, e poi riscambiato con $GLOBALS["baz"]. Questo non è il modo per collegare $bar nell'ambito della chiamata con qualcos'altro usando il meccanismo di riferimento, poiché $bar non è disponibile nella funzione foo (è rappresentato da $var, ma $var possiede soltanto il contenuto della variabile e non il nome del valore collegato nella tabella dei simboli). Si può utilizzare restiture i riferimenti per fare riferimenti a variabili selezionate dalla funzione.

Si può passare una variabile ad una funzione per riferimento, modificandone gli argomenti. La sintassi è la seguente: <?php function foo(&$var) { $var++; } $a=5; foo($a); // $a adesso è 6 ?> Il simbolo del riferimento non si scrive nella chiamata della funzione, ma solo nella sua definizione. La definizione della funzione basta da sola per passare correttamente un argomento per riferimento. Dal PHP 5.3.0, si avrà un warning indicante che "call-time pass-by-reference" (il passaggio per riferimento al momento della chiamata) è deprecato quando si usa Amp foo(Amp$a);. Da PHP 5.4.0, il passaggio per riferimento al momento della chiamata è stato rimosso, quindi usarlo provoca un errore fatale.

Le seguenti cose possono essere passate per riferimento: Variabili, es. foo($a) Operatore New, es. foo(new foobar()) Riferimento restituito da una funzione, es. <?php function foo(&$var) { $var++; } function &bar() { $a = 5; return $a; } foo(bar()); ?> Vedere anche le spiegazioni sulla restituzione per riferimento.

Nessun'altra espressione dovrebbe essere passata per riferimento, poiché il risultato sarebbe indefinito. Per esempio, i seguenti esempi di passaggio per riferimento non sono validi: <?php function foo(&$var) { $var++; } function bar() // Notare l'assenza di & { $a = 5; return $a; } foo(bar()); // Produce un errore fatale da PHP 5.0.5 foo($a = 5); // Expressione: non una variabile foo(5); // Genera un errore fatale ?> Questi requisiti sono validi per PHP 4.0.4 e seguenti.

La restituzione per riferimento è utile quando si vuole usare una funzione per trovare quale variabile un riferimento dovrebbe limitare. Non utilizzare il ritorno per riferimento per incrementare le prestazioni, l'engine è capace di ottimizzare il codice per proprio conto. Restituire valori per riferimento solo se si hanno validi motivi tecnici. Per restituire per riferimento, si usa questa sintassi: <?php class foo { public $value = 42; public function &getValue() { return $this->value; } } $obj = new foo; $myValue = &$obj->getValue(); // $myValue è un riferimento a $obj->value, che vale 42. $obj->value = 2; echo $myValue; // stampa il nuovo valore di $obj->value, es. 2. ?> In questo esempio, la proprietà dell'oggetto restituito dalla funzione getValue viene impostata, non la copia, come sarebbe stato senza l'uso della sintassi del riferimento.

Nota: Diversamente dal passaggio di un parametro, bisogna utilizzare Amp in entrambi i posti - nella dichiarazione per indicare che si vuole restituire per riferimento, e non per copia come di consueto, e per indicare nella chiamata, il collegamento del riferimento, piuttosto che l'usuale assegnazione che verrebbe fatta per $myValue.
Nota: Se si tenta di restituire un valore per riferimento da una funzione con la sintassi: return ($this->value); questo non funzionerà poiché si sta tentando di restituire per riferimento il risultato di un' espressione, e non una variabile. Da una funzione, si possono restituire per riferimento solo le variabili. A partire da PHP 4.4.0 e PHP 5.1.0, un errore E_NOTICE è lanciato se il codice cerca di restituire un'espressione dinamica o un risultato dell'operatore new.

Per utilizzare il riferimento restituito, occorre usare l'assegnazione per riferimento: <?php function &collector() { static $collection = array(); return $collection; } $collection = &collector(); $collection[] = 'foo'; ?> Al fine di passare il riferimento a un'altra funzione che richiede un riferimento si può usare questa sintassi: <?php function &collector() { static $collection = array(); return $collection; } array_push(collector(), 'foo'); ?>

Nota: Si noti che array_push(Ampcollector(), 'foo'); non funzionerà, ma creerà un errore fatale.

Quando si cancella un riferimento, si rompe il collegamento tra il nome della variabile e il contenuto della variabile. Questo non significa che il contenuto della variabile venga distrutto. Per esempio: <?php $a = 1; $b =& $a; unset($a); ?> non cancella $b, ma solo $a.

Di nuovo, può essere utile pensare a questo con un'analogia col comendo Unix unlink.

Diversi costrutti in PHP sono implementati attraverso il meccanismo dei riferimenti, dove ogni cosa detta precedentemente, si applica anche a questi costrutti. Alcuni, come il passaggio e la restituzione per riferimento, sono stati menzionati sopra, gli altri sono:

Il riferimento

Quando si dichiara una variabile come global $var di fatto si crea un riferimento ad una variabile globale. Questo ha lo stesso significato, dell'espressione: <?php $var =& $GLOBALS["var"]; ?>

Questo significa, per esempio, che cancellando $var non si cancella la variabile globale.

In un metodo di un oggetto, $this è sempre un riferimento all'oggetto chiamante.