I namespace permettono di creare insieme di classi , intefacce , funzioni e costanti per risolvere un determinato problema.
Concettualmente sono molto simili alle cartelle di un filesystem di windows e sono stati introdotti dalla versione 5.3
La definizione viene fatta tramite il richiamo del nome nel seguente modo
<?php namespace Esempio; class MyClass { // Corpo della classe esempio }
Servono per riutilizzare classi già esistenti. Si dividono in
- Nomi non qualificati non hanno l’elemento separatore \ ad esempio MyClass
- Nomi qualificati con il separatore progetto\MyClass
- Nomi completamente Qualificati ad esempio progetto1\sottoprogetto\MyClass
che appunto ricorda molto il concetto di file in cartelle nel filesystem di Windows.
Non è ammessa una dichiarazione prima di loro ossia una codice del tipo
<html> <?php namespace progetto; ?>
Restituirà un messaggio di errore di statement.
Sarà invece possibile dichiarare
<?php namespace progetto\sottoprogetto\Livello; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } ?>
In ogni file sarà però possibile dichiarare multipli namespace nel seguente modo
<?php namespace progetto; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } namespace secondoprogetto; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } ?>
Con l’introduzione dei namespace sono stati introdutti anche
- _NAMESPACE_ costante che contiene una stringa con il namespace corrente. nel caso di namespace globale assumerà valore di stringa vuota
- namespace è una keyword che serve per dichiarare un namespace e accedere ai suoi elementi come con l’operatore self.
Vediamo un esempio per chiarire tutto
<?php namespace Progetto; echo '"', __NAMESPACE__, '"'; // mostrerà l'output di "Progetto" ?>
nel caso invece di codice globale avremo
<?php echo '"', __NAMESPACE__, '"'; //e in output avremo la stringa vuota. ?>
Dalla versione 5.6 inoltre il php permette anche nel caso di namespace l’aliasing
Definizione aliasing indica la situazione in cui una stessa posizione di memoria è associata a nomi simbolici diversi all’interno di un programma. Come nel caso dei puntatori.
Ad esempio
<?php namespace foo; use My\Full\Classname as Another; // this is the same as use My\Full\NSname as NSname use My\Full\NSname; // importing a global class use ArrayObject; // importing a function (PHP 5.6+) use function My\Full\functionName; // aliasing a function (PHP 5.6+) use function My\Full\functionName as func; // importing a constant (PHP 5.6+) use const My\Full\CONSTANT; $obj = new namespace\Another; // instantiates object of class foo\Another $obj = new Another; // instantiates object of class My\Full\Classname NSname\subns\func(); // calls function My\Full\NSname\subns\func $a = new ArrayObject(array(1)); // instantiates object of class ArrayObject // without the "use ArrayObject" we would instantiate an object of class foo\ArrayObject func(); // calls function My\Full\functionName echo CONSTANT; // echoes the value of My\Full\CONSTANT ?> in questo caso si utilizza l'operatore use ..... as ...;
Se non viene definita la parola chiave namespace le funzioni saranno definite nello spazio globale e quindi ne dobbiamo fare ricorso come nel seguente esempio
Senza alcuna definizione di namespace, tutte le definizioni di classi e funzioni sono collocate nello spazio globale, come in PHP prima che fossero supportati gli spazi dei nomi. Prefixing un nome con \ specificherà che il nome è richiesto dallo spazio globale anche nel contesto dello spazio dei nomi.
Utilizzo Namespace e spazio globale
<?php namespace A\B\C; /* Questa funzione si trova in A\B\C\fopen */ function fopen() { /* ... */ $f = \fopen(...); // chiamata globale alla funzione fopen return $f; } ?>
L’inclusione di file con questo meccanismo è realmente molto immediato vi basterò fare
<?php //test.php namespace test { include 'test1.inc'; echo '-',__NAMESPACE__,'-<br />'; } ?> <?php //test1.inc echo '-',__NAMESPACE__,'-<br />'; ?> Risultato del testo.php -- -testo-
Vediamo un altro esempio per meglio comprendere consideriamo la funzione
<?php namespace A\B\C; const E_ERROR = 4; function strlen($str) { return \strlen($str) - 1; } echo E_ERROR, "\n"; // stampa il valore "4" echo strlen('hi'), "\n"; // stampa il valore "1" if (is_array('hi')) { // stampa il valore non è un array echo "è un array\n"; } else { echo "non è un array\n"; } ?> Facciamo un esempio conclusivo per comprendere la risoluzione dei nomi namespace
<?php namespace A; use B\D, C\E as F; // function calls foo(); // prima cerca di chiamare "foo" definito nello spazio dei nomi "A" // quindi chiama la funzione globale "foo" \foo(); // chiama la funzione "foo" definita nell'ambito globale my\foo(); // chima la funzione "foo" definita nel namespace "A\my" // class references new B(); // crea l'ggetto classe "B" definito nel namespace globale "A" //altrimenti lo cerca in "A\B" new D(); // crea l'oggetto classe "D" definito nel namespace "B" altrimenti controlla in B\D new F(); // Crea l'oggetto in classe "E" definito nel namespace "C" altrimenti prova a caricarlo in "C\E" new \D(); // Crea l'oggetto "D" definito in classe globale // if not found, it tries to autoload class "D" B\foo(); // chiama la funzione "foo" dal namespace "A\B" B::foo(); // chiama il metodo "foo" di classe "B" definito in classe "A" altrimenti cerca di caricarlo in classe "A\B" \A\B::foo(); // chiama il metodo "foo" di classe "B" dal namespace "A" altrimenti prova a caricarlo dalla classe "A\B" ?> A questo punto possiamo vedere un esempio totale per comprenderne il funzionamento
<?php namespace cartella\nome; class MiaClasse {} function miafunzione() {} const MYCONST = 1; $a = new MiaClasse; $c = new \cartella\nome\MiaClasse; $a = strlen('hi'); $d = namespace\MYCONST; $d = __NAMESPACE__ . '\MYCONST'; echo constant($d); ?>