Negli ultimi anni in PHP sono state introdotte caratteristiche simili a quelle dei linguaggi orientati alla programmazione ad oggetti, come ad esempio C++ e Java. Le innovazioni principali sono state incluse in PHP4, e completate poi in PHP5. Anche se non usiamo la programmazione orientata agli oggetti, è bene capire il meccanismo alla base delle novità: le regole di assegnazione delle variabili, siano esse primitive oppure oggetti, riguardano potenzialmente qualsiasi blocco di codice in PHP. La conoscenza di queste regole aiuta a leggere il codice altrui e chiarisce i dubbi che possono nascere durante la fase di debug.

Una di queste regole riguarda l'assegnazione di variabili secondo una modalità simile al concetto di puntatore. Anche se non si tratta di veri e propri puntatori (come in C++) ma di semplici identificatori, il nome puntatore rende bene l'idea. Quando assegniamo una variabile, di solito trasferiamo solo il valore della variabile, senza coinvolgere l'identificatore. Ad esempio

$a = 10 ;

$b = $a ;

$b++ ;

print $a.' - '.$b ;

qui la variabile $b viene incrementata, mentre la variabile $a resta immutata. Il risultato del print è quindi 10 – 11. Fin qui nulla di nuovo, ma la situazione cambia se scriviamo

$a = 10 ;

$b = &$a ;

$b++ ;

print $a.' - '.$b ;

Notiamo il simbolo & (e commerciale) davanti alla variabile $a. La sintassi permette di scrivere il simbolo & sia subito prima del simbolo $ (dollaro), sia “in mezzo”, tra il simbolo = (uguale) e il dollaro. L'utilizzo del simbolo & emula, in parte, il comportamento dei puntatori. In questo caso le due variabili $a e $b sono due identificatori distinti ma “puntano” alla stessa locazione di memoria, ovvero condividono lo stesso valore. Ciò significa che, quando incrementiamo $b, incrementiamo lo stesso valore puntato dall'identificatore $a. Il risultato del print sarà adesso 11 – 11, perché entrambi gli identificatori $a e $b puntano alla stessa variabile.

La regola appena vista permette di passare un riferimento alla variabile, anziché il valore della variabile. Nel caso qui sopra ciò non da alcun vantaggio, ed è lecito chiedersi a cosa può servire una sintassi del genere. La questione si fa più interessante se passiamo un riferimento alla variabile come argomento di una funzione

function testPrimitive(&$a) {

$my_a =& $a ;

print 'Local variable: '.++$my_a.'<br/>' ;

}

osserviamo che, quando trattiamo una funzione, che il simbolo & va usato due volte per ogni variabile: esso va inserito sia nella firma della funzione, quando definiamo gli argomenti, sia nel corpo della funzione, quando usiamo la variabile $a per assegnare un valore a $my_a.

Proviamo ad invocare la funzione per vedere cosa succede

$var_a = 10 ;

testPrimitive($var_a) ;

print '<p>Original value: '.$var_a.'</p>' ;

che ritorna come risultato

Local variable: 11

Original value: 11

L'esempio dovrebbe mostrare perché il passaggio di parametri tramite riferimento (o puntatore) anziché tramite valore, può soddisfare molte esigenze. Spesso usiamo la keyword global per trasformare delle variabili locali (quelle usate “dentro” la funzione) in variabili globali (definite “fuori” dalla funzione), allo scopo di condividerne i valori. Passando un riferimento alla variabile possiamo memorizzare il valore di ritorno all'interno della variabile usata come argomento, evitando l'uso della variabili global. Ciò risulta utile se scriviamo delle funzioni che devono modificare i dati in ingresso: in molti casi l'uso del simbolo & è la soluzione più semplice, almeno rispetto all'uso (o abuso) delle variabili global, oppure al ritorno di strutture come gli array.

La comprensione del meccanismo aiuta inoltre a capire alcuni aspetti della programmazione Object Oriented. Quando trattiamo gli oggetti, il comportamento standard degli identificatori è quello visto sopra. Consideriamo ad esempio

function testObject($o) {

$my_o = $o ;

$my_o->increment() ;

print '<p>Local object: '.$my_o->getId() ;

}

e la chiamata

$obj = new TestVO(42) ;

testObject($obj) ;

print '<p>Original object: '.$obj->getId() ;

dove TestVO è una semplice classe ValueObject, che incapsula (cioè “avvolge”) un'unica variabile numerica, ovvero un ID (per un'introduzione al pattern VO vedi qui).

In questo caso, avendo a che fare con oggetti anziché variabili primitive, l'argomento $o della funzione testObject viene sempre e comunque trattato come un riferimento, e non come un valore. Si potrebbe dire, usando un'espressione poco rigorosa ma speriamo efficace, che nel caso degli oggetti il simbolo & è “sottinteso per default”. Per questo motivo, soprattutto nella programmazione OOP, si parla di identificatori (o puntatori) all'oggetto, anziché di variabili.

L'uso del simbolo & non è obbligatorio, ma può tornare utile in molti casi. E' bene ricordarsene, soprattutto quando sbirciamo il codice scritto da altri e vogliamo capire perché alcune variabili sono precedute dai simboli &$, che di primo acchito potrebbe confondere chi non conosce la sintassi o l'utilizzo dei puntatori.