PHP è forse il linguaggio più popolare sul web, soprattutto nell'ambito dei pacchetti AMP, dove Apache, MySQL e PHP lavorano in concerto offrendo un framework particolarmente adatto allo sviluppo di applicazioni web. I sostenitori delle piattaforme antagoniste, come ad esempio Java o .NET spesso cercano di mettere in evidenza alcuni limiti di PHP, tra cui: l'esecuzione mediante interpretazione anziché compilazione, la ridotta scalabilità e il fatto di non supportare a pieno la programmazione Object Oriented. Per nostra fortuna abbiamo una risposta per ciascun argomento: esistono compilatori per PHP, come ad esempio Phalanger e HipHop. Là dove PHP non garantisce scalabilità del codice è sempre possibile scalare il parco macchine, con costi minori dell'equivalente sviluppo software. L'unico aspetto oscuro è la questione della programmazione OOP, come abbiamo già discusso qui.

Hanno ragione i puristi quando dicono che PHP non è strutturato ad oggetti, perché di fatto è possibile scrivere un'intera applicazione in PHP senza tirare in ballo concetti come istanze, costruttori, polimorfismo ed ereditarietà. Dal punto di vista pratico si possono comunque ottenere ottimi risultati con la programmazione OOP, col vantaggio della libertà di scegliere lo stile più adatto: programmazione strutturata o programmazione ad oggetti.

Oggi cercheremo di capire, con un esempio pratico, perché la programmazione OOP in PHP alimenta alcune controversie. L'obiettivo è prendere due piccioni con una fava: fare chiarezza sulla questione e vedere l'applicazione concreta degli attributi statici in PHP, che ben si prestano allo scopo.

Sintassi

Iniziamo col vedere la sintassi necessaria per fare qualche esperimento. Consideriamo un oggetto in PHP, ad esempio un'istanza $test_a della classe TestObject. In questo caso un normale attributo di classe sarà accessibile come

$test_a->my_field

dove il campo $my_field potrebbe essere definito come

public $my_field ;

La sintassi cambia quando definiamo un attributo di classe statico, ovvero

public static $public_one

in questo caso non possiamo usare la stessa sintassi dei normali attributi di classe, perché l'interprete PHP richiede una sintassi specifica per i riferimenti alle classi, che è diversa da quella usata per accedere agli oggetti. La sintassi corretta è

$test_a::$public_one ;

Notiamo l'uso dei due punti (::) al posto della freccetta (->) tra l'identificare dell'oggetto e il nome del campo statico, nonché la "doppia" presenza del dollaro ($). Una sintassi di questo tipo enfatizza il fatto che l'attributo $public_one è una proprietà della classe TestObject, e solo in quanto tale è presente (anche) come attributo dell'oggetto $test_a.

Un modo di verificarlo è quello di assegnare un valore al campo $public_one e poi confrontare i valori ritornati dalle diverse sintassi

$test_a::$public_one = 17 ;

echo $test_a::$public_one.'<br/>' ;

echo $test_b::$public_one.'<br/>' ;

echo TestObject::$public_one.'<br/>' ;

dove $test_b è un'altra istanza della classe TestObject. Il risultato sarà una fila di valori uguali (ovvero 17), perché il campo $public_one è lo stesso in tutti i casi. Questo è proprio lo scopo degli attributi statici: avere un unico valore condiviso da tutte le istanze, a differenza dei normali attributi degli oggetti, che invece hanno in genere un valore diverso per ciascuna istanza.

Contesto degli oggetti

Una volta chiarita la sintassi, possiamo capire quali sono le differenze tra PHP e l'approccio standard della programmazione ad oggetti. Nella OOP tradizionale, una volta caricata una classe (nel nostro caso la TestObject), l'intera applicazione condividerà lo stesso riferimento alla classe. Ciò significa che se in un'altra pagina useremo la stessa classe, quando leggiamo il valore del campo $public_one troveremo sempre l'ultimo valore assegnato (in questo caso 17).

Questo non succede in PHP: se il codice visto sopra si trova nella pagina pagina_1.php, e proviamo a leggere il valore del campo $public_one nella pagina_2.php, troveremo un valore diverso.

Di primo acchito si potrebbe pensare che ciò dia ragione a chi sostiene che PHP non sia un linguaggio ad oggetti. Da un punto di vista è corretto, ma basta cambiare prospettiva per arrivare alla conclusione opposta. La questione sta nella definizione del contesto in cui vengono caricate le classi. Nell'approccio tradizionale, come ad esempio in Java, abbiamo un class-loader per ciascun contesto, che di solito coincide con l'intera applicazione. Se invece cambiamo contesto, ovvero cambiamo applicazione, ci troveremo quasi sicuramente ad usare un nuovo class-loader. In tal caso anche un linguaggio OOP tradizionale presenta lo stesso comportamento di PHP: gli attributi statici di una stessa classe avranno valori diversi perché appartenenti a contesti diversi.

Cosa cambia allora in PHP? Come dicevamo prima, si tratta di una questione di prospettiva. In PHP il contesto in cui vivono le classi è quasi sempre la pagina web, ovvero una classe rimane la stessa finché restiamo nella stessa pagina. Se cambiamo pagina cambiamo contesto, esattamente come quando cambiamo applicazione nella OOP tradizionale.

Tutto a posto, quindi. Anche se PHP non è rigorosamente un linguaggio OOP, di fatto permette di fare tutto quello che facciamo con la normale programmazione OOP. Ad esempio, se vogliamo che una classe sia la stessa per un'intera applicazione, ovvero vogliamo condividere uno stesso contesto tra pagine diverse, ci basterà scegliere un modo di passare l'informazione da una pagina all'altra. Il modo più semplice di farlo è affidandosi alla sessione PHP, come vedremo nelle prossime puntate.