La déclaration d'un namespace se fait généralement dans un fichier à part. Il est déconseillé d'en déclarer plusieurs à l'intérieur d'un seul et même fichier, mais c'est possible.
Déclaration d'un namespace
Pour déclarer un namespace, il faut utiliser la commande
namespace suivi du nom du namespace à créer. Rien ne doit être placé avant, que ce soit du HTML ou un simple retour à la ligne. Aucune instruction ne doit d'ailleurs être écrite avant la déclaration du namespace (sauf l'instruction
declare). Bref, voici un exemple tout bête :
Code : PHP | <?php
namespace MonNamespace; // Déclaration du namespace.
// Toutes les constantes, fonctions et classes déclarées ici feront partie du namespace MonNamespace.
?>
|
Afin d'être sûr qu'on a créé un nouveau namespace, on va créer une fonction ayant le même nom qu'une autre fournie par PHP, puis exécuter le code.
Code : PHP | <?php
namespace MonNamespace;
function strlen()
{
echo 'Hello world !';
}
?>
|
Quand vous ouvrez cette page, aucune erreur n'est lancée ! La fonction
strlen() a été créée
dans notre nouveau namespace. Vous pouvez même l'appeler de cette façon :
Code : PHP | <?php
namespace MonNamespace;
function strlen()
{
echo 'Hello world !';
}
strlen();
?>
|
Et vous verrez qu'à l'écran s'affichera
« Hello world ! ».
Euh attends… Qu'est-ce qui s'est passé là ?
Ce qui s'est passé est très simple. Nous avons créé un nouveau namespace, et tout ce qui suit cette déclaration fait partie de ce namespace, c'est donc pour ça que ce n'est pas la fonction
strlen() du namespace global qui a été appelée.
Et si je veux appeler une fonction du namespace global, je fais comment ?
Il vous suffit tout simplement de faire précéder le nom de la fonction d'un backslash (
\), comme ceci :
Code : PHP | <?php
namespace MonNamespace;
function strlen()
{
echo 'Hello world !';
}
echo \strlen('Hello world !');
?>
|
Ce qui affiche bien « 13 ».
Si vous incluez ce fichier (que l'on nomme par exemple
MonNamespace.ns.php) dans un autre (par exemple
index.php), alors le code contenu dans
index.php fera partie du namespace global, et non de
MonNamespace !
Déclaration de plusieurs namespaces dans un même fichier
C'est déconseillé, mais possible. Vous pouvez déclarer plusieurs namespaces à la suite, comme ceci :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | <?php
namespace A;
function quelNamespace()
{
echo 'A';
}
quelNamespace(); // Affiche « A ».
namespace B;
function quelNamespace()
{
echo 'B';
}
quelNamespace(); // Affiche « B ».
?>
|
Si vous décidez de déclarer plusieurs namespaces au sein d'un même fichier, il est préférable d'utiliser une autre méthode. En effet, mieux vaut utiliser les accolades :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | <?php
namespace A
{
function quelNamespace()
{
echo 'A';
}
quelNamespace();
}
namespace B
{
function quelNamespace()
{
echo 'B';
}
quelNamespace();
}
?>
|
Le résultat observé est le même. Sachez aussi qu'aucun code ne peut être écrit en dehors de ces accolades.
Et si je veux écrire du code dans le namespace global, je fais comment ?
Il vous suffit simplement d'ouvrir une nouvelle paire d'accolades, précédée du simple mot
namespace, comme ceci :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | <?php
namespace A
{
function quelNamespace()
{
echo 'A';
}
quelNamespace();
}
namespace B
{
function quelNamespace()
{
echo 'B';
}
quelNamespace();
}
namespace // Le code contenu dans ce namespace fera partie du namespace global.
{
echo strlen('Hello world !');
}
?>
|
Et à l'écran s'affichera
« AB13 ». Tous les namespaces ont donc bien été exécutés, et le dernier fait bien partie du namespace global puisque
strlen() a été correctement appelé.
Tu nous as dit que si une constante, fonction ou classe n'existait pas dans le namespace actuel, alors PHP irait la chercher dans le namespace global. Ta conclusion est donc un peu trop hâtive, non ?
Exact. Puisqu'il vous faut encore plus de preuves et que vous ne me croyez pas, je vais vous présenter une constante magique.
__NAMESPACE__
Cette constante magique est une chaîne de caractères qui contient le nom du namespace dans lequel on se trouve actuellement. Si on est dans l'espace de nom global, alors cette constante est vide.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | <?php
namespace A
{
echo __NAMESPACE__;
}
namespace B
{
echo __NAMESPACE__;
}
namespace
{
echo __NAMESPACE__;
}
?>
|
Et à l'écran s'affiche bien «
AB ». Le dernier namespace est donc bien le namespace global. Convaincu ?
Déclaration de sous-namespaces
Il est dommage de se limiter à la création de simple namespaces, au même titre que de simples dossiers à la racine. Il est donc possible, fort heureusement, de créer des
sous-namespaces (vous pouvez en créer une infinité).
Pour créer un namespace à l'intérieur d'un autre, on écrira l'arborescence du namespace. Par arborescence j'entends tous les namespaces parents. Si je veux créer un namespace
B dans
A, alors
A sera le namespace parent de
B, et il va falloir le spécifier lors de la création de
B.
Lorsque vous séparez deux namespaces, il faut les séparer par un backslash (le revoici, celui-là), comme les dossiers sous Windows. Ainsi, si on veut créer
B dans
A, on fera comme ça :
Code : PHP | <?php
namespace A\B;
echo __NAMESPACE__;
?>
|
Et à l'écran s'affiche... «
A\B » ! En effet, quand on spécifie un namespace, on part toujours du premier namespace, puis on liste tous les sous-namespaces. Ainsi, le namespace
B à proprement parler n'existe pas.
Notez que le namespace
A est automatiquement créé si on décide de créer le namespace
A\B. Le namespace
A est donc vierge et on peut le remplir par la suite :
Code : PHP | <?php
namespace A\B
{
echo __NAMESPACE__;
}
namespace A
{
echo __NAMESPACE__;
}
?>
|
À l'écran s'affichera bien «
A\BA ».
Accéder à un élément d'un namespace différent
Créer des namespaces c'est bien, mais pouvoir appeler des constantes, fonctions ou classes d'un namespace différent, c'est encore mieux. Pour cela, il suffit de spécifier le namespace auquel appartient l'élément juste avant de l'appeler. Comme pour les fichiers, il y a deux façons de procéder.
- De façon relative : l'appel de l'élément dépendra du namespace dans lequel vous êtes. Celui-ci est relatif au namespace courant.
- De façon absolue : l'appel de l'élément se fait en partant du namespace global puis en listant tous les sous-namespaces jusqu'au namespace souhaité.
Prenons un exemple tout simple :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | <?php
namespace A\B
{
function getNamespace()
{
echo __NAMESPACE__;
}
}
namespace A
{
B\getNamespace(); // Appel de façon relative.
\A\B\getNamespace(); // Appel de façon absolue.
}
?>
|
Vous revoyez encore ce backslash. Vous n'avez pas fini de le voir, dans le monde des namespaces sous PHP, c'est lui qui est utilisé pour séparer deux éléments.
Un peu de vocabulaire
Quand vous appelez une constante, fonction ou classe, alors le nom de l'élément que vous appelez est
qualifié ou
non qualifié.
- On dit que le nom de l'élément est qualifié si le namespace dans lequel il se trouve est spécifié. Exemple : B\fonction() et \A\B\fonction() sont tous les deux des éléments qualifiés.
- On dit que le nom de l'élément est non qualifié si le namespace dans lequel il se trouve n'est pas spécifié. Exemple : fonction() est un élément non qualifié.
Ceci m'oblige à revenir sur quelque chose que je vous ai dit plus tôt. Je vous avais dit que si la constante, fonction ou classe appelée n'existait pas dans le namespace actuel, alors PHP irait chercher dans le namespace global. En fait, c'est le cas uniquement si le nom de l'élément est non qualifié. S'il est qualifié, alors PHP lèvera une erreur directement, sans aller chercher dans le namespace global.
Donc si je veux appeler un élément du namespace courant, celui-ci sera forcément un élément non qualifié, à moins que je l'appelle de façon absolue, c'est ça ?
Pas vraiment. Il existe un moyen d'appeler un élément du namespace courant de façon relative tout en étant qualifié. Pour cela, il y a le mot-clé
namespace. Vous le connaissez déjà, c'est lui qui permet de déclarer un nouveau namespace, mais je vais vous présenter ici une autre de ces fonctionnalités : pouvoir appeler un élément de l'espace courant de façon relative tout en étant qualifié. Il s'utilise simplement comme ceci :
Code : PHP | <?php
namespace A;
echo strlen('Hello world !'); // Appel relatif, élément non qualifié.
echo namespace\strlen('Hello world !'); // Appel relatif, élément qualifié. Résultat : erreur fatale car fonction inexistante.
?>
|
Comme vous l'aurez peut-être deviné,
namespace représente le namespace actuel. Pour ceux qui savent programmer orienté objet, le mot-clé
namespace peut être comparé au mot-clé
self. L'un représente le namespace, l'autre la classe.