Internet cambia e le esigenze dei programmatori variano e crescono con il passare del tempo. Anche PHP, come tutti gli altri linguaggi di programmazione, segue questo corso (che, per quanto mi riguarda, non posso definire come suo corso dato che spesso molte scelte sono imposte dal sistema esterno al team) e pian piano sta cercando di colmare alcune lacune che molto ritengono altamente compromettenti.
In attesa della versione 6 del linguaggio, che - speranza di tutti i programmatori PHP - dovrebbe colmare quel gap sintattico e tecnologico che attualmente rende PHP eterno inseguitore nella corsa al linguaggio più completo, lo Zend team sta rilasciando PHP 5.3 (si parla di inizio 2008). Quest'ultima versione del linguaggio aggiunge nuove funzionalità interessanti, alcune delle quali avrebbero dovuto già far parte della versione 5.0 ma sono state scartate o posticipate per motivi a noi sconosciuti (si mormora di una difficoltà nel far aderire il motore Zend 2.0 a queste funzionalità, ma a quanto pare il fatto che queste funzionalità siano state implementate probabilmente nega questa affermazione).
In questa breve serie di articoli faremo una rapida introduzione alle varie funzionalità, molte delle quali risulteranno gradite a che spera che PHP completi la sua crescita arrivando prima o poi ad avere un supporto realmente completo alla programmazione ad oggetti ed alla meta-programmazione.
Namespace
Iniziamo proprio con la prima delle grandi escluse tra le funzionalità che avrebbero dovuto stravolgere il mondo della programmazione PHP all'epoca dell'uscita della versione 5.0: i namespace. Per chi non ne fosse a conoscenza i namespace sono un costrutto semantico che permette al programmatore di evitare la collisione tra i nomi di classi, funzioni o altre strutture racchiudendole all'interno di uno spazio di nomi indipendente dal codice restante. Il codice può accedere successivamente a queste strutture definite all'interno del namespace anteponendo al nome della struttura il namespace stesso oppure segnalando all'interprete la volontà di includere nello spazio di nomi corrente tutto il contenuto di un determinato namespace.
I namespace potrebbero quindi essere visti come dei contenitori semantici che contengono dei normali costrutti PHP i quali possono essere interrogati per richiedere determinati elementi oppure possono essere rovesciati all'interno di un altro contenitore al fine di ingrandire lo spazio dei nomi correnti se necessario. Sono molto utili: vediamo perché nella prossima pagina.
Con i namespace siamo quindi in grado di sostituire quegli "accrocchi sintattici" che attualmente vengono utilizzati per evitare la collisione tra i nomi di strutture definite in librerie differenti. Prima di procedere forse comunque è il caso di spiegare cosa definisco un accrocchio (termine pressoché caduto in disuso ed utilizzato da me in circostanze del tutto discutibili): con accrocchio mi riferisco alla classica denominazione delle classi che suggerisce di anteporre al nome della classe stessa il nome delle directory in cui questa è definita separate da underscore.
Lo Zend Framework è in assoluto uno dei seguaci più accaniti dell'argomento, andando a generare a volte nomi di classi di lunghezza quantomeno singolare: Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive
. Giusto per specificare qui non ci troviamo di fronte a nomi lunghi al fine di auto-commentare il comportamento di una classe (si veda ciò che accade in Cocoa), ma ad una linea guida forzata.
Tornando a noi, quando si parla di programmazione è spesso più difficile spiegare in modo teorico un argomento che mostrare come utilizzare una determinata funzionalità in un contesto del tutto casuale. Vediamo come definire un namespace e popolarlo con delle strutture:
<?php
// path: it/html/superusefullib/DoesNothing.php
namespace it::html::superusefullib;
const AUTHOR = 'Gabriele Farina';
class DoesNothing
{
}
function testDoesNothing()
{
new DoesNothing();
}
?>
Come possiamo notare nulla di così complesso: un namespace viene definito dal costrutto namespace
(che, si mormora qua e la nelle mailing list, potrebbe essere sostituito con la keyword package) seguito dal nome del namespace. Il nome del namespace è formato da una serie di parole (per convenzione lowercase) separate da una coppia di due punti. Una volta definito il nostro namespace abbiamo il famoso contenitore dal quale attingere gli elementi (nel caso specifico la classe DoesNothing
, la funzione testDoesNothing
e la costante AUTHOR
). Vediamo ora i diversi modi con cui è possibile attingere dal contenitore:
<?php include_once "it/html/superusefullib/DoesNothing.php"; // 1 $doesNothing = new it::html::superusefullib::DoesNothing(); // 2 use it::html::superusefullib; $doesNothing = new superusefullib::DoesNothing(); // 3 use it::html::superusefullib::DoesNothing; $doesNothing = new DoesNothing(); // 4 use it::html::superusefullib as notsousefullib; use it::html::superusefullib::DoesNothing as DoesSomething; $doesNothing = new notsousefullib::DoesNothing(); $doesNothing = new DoesSomething(); ?>
Fondamentalmente abbiamo quattro modi per accedere alle strutture definite:
- Accediamo alla struttura dati anteponendo il namespace al nome della struttura che ci interessa;
- Importiamo (usando la parola chiave
use
) il namespace nello spazio dei nomi corrente (nel nostro esempio quello globale), ed accediamo alla struttura usando solamente la parte finale del nome del namespace; - Importiamo direttamente la struttura che ci serve, utilizzandola successivamente come se fosse stata definita nello stesso spazio dei nomi. Questo sistema non funziona per le costanti;
- Infine possiamo specificare degli alias, da usare sia per i namespace che direttamente per le strutture importate.
Alcuni punti da tenere in considerazione
Che dire: i namespace offrono sicuramente molta utilità ed una bassa complessità che pian piano diventa nulla una volta presa padronanza del costrutto. In generale comunque ci sono alcuni punti da tenere in considerazione quando si lavora con i namespace:
- La costante
__NAMESPACE__
che all'interno del namespace acquisisce direttamente come valore il nome del namespace attuale; - L'utilizzo del namespace vuoto rappresentato da una coppia di due punti (
::
) che serve per accedere al namespace globale. Il namespace è il contenitore in cui finiscono tutte le classi, le funzioni e le costanti che sono definite senza namespace; - All'interno di un namespace, se l'interprete non trova un simbolo al quale si cerca di accedere definito nello stesso namespace, andrà a ricercarlo all'interno delle funzionalità builtin. Se necessitiamo di accedere a funzioni globali definite in un'altra posizione, è necessario anteporre al nome del simbolo il namespace globale.
- La funziona
__autoload
da PHP 5.3 in avanti riceverà come argomento l'internoqualified name
della classe; con qualified name si intende il nome della classe preceduto dal suo namespace, sia questo un namespace definito dall'utente o il namespace globale. Sarà quindi importante prendere in considerazione questo fatto quando si andranno ad aggiungere i namespace al proprio progetto all'uscita di PHP 5.3, ed apportare tutte le modifiche del caso; - Le Reflection API sono state estese al fine di includere anche il supporto per i namespace. è stato aggiunto alle classi
ReflectionClass
eReflectionFunction
il metodogetNamespace
che restituisce un'istanza della classeReflectionNamespace
rappresentante lo spazio dei nomi in cui la struttura è stata definita. Tramite questa classe è possibile interrogare il namespace corrente per poter recuperare diverse informazioni attraverso i metodigetName
,getClasses
,getFunctions
,getFiles
.
Conclusione
Abbiamo introdotto la prima funzionalità, forse la più interessante ma sicuramente la più attesa, di questa imminente nuova versione di PHP 5. Penso sia inutile dire che probabilmente questa funzionalità varierà parecchio il modo in cui le librerie PHP verranno sviluppate dal 2008 in avanti, e quindi penso sia inutile anche suggerire di acquisire padronanza con questa - semplice - struttura sintattica. I namespace sono una funzionalità molto amata da molti programmatori (soprattutto chi proviene da altre realtà in cui il concetto è alla base del linguaggio dalla notte dei tempi - si veda Java, C#, C++ e molti altri) e soprattutto ancora più amata da chi ai programmatori dice cosa e come fare. Quindi acquisire la tecnica faciliterà sicuramente il passaggio indolore e rapido ad un nuovo approccio che si andrà ad affermare a breve.