Les espaces de nomsIntroduction aux espaces de noms
Que sont les espaces de noms ? Dans leur définition la plus large, ils représentent
un moyen d'encapsuler des éléments. Cela peut être conçu comme un concept
abstrait, pour plusieurs raisons. Par exemple, dans un système de fichiers, les
dossiers représentent un groupe de fichiers associés et servent d'espace de noms
pour les fichiers qu'ils contiennent. Un exemple concret est que le fichier
foo.txt peut exister dans les deux dossiers
/home/greg et /home/other, mais que
les deux copies de foo.txt ne peuvent pas co-exister
dans le même dossier. De plus, pour accéder au fichier foo.txt
depuis l'extérieur du dossier /home/greg, il faut préciser
le nom du dossier en utilisant un séparateur de dossier, tel que
/home/greg/foo.txt. Le même principe s'applique aux
espaces de noms dans le monde de la programmation.
Dans le monde PHP, les espaces de noms sont conçus pour résoudre deux problèmes
que rencontrent les auteurs de bibliothèques et d'applications lors de la réutilisation
d'éléments tels que des classes ou des bibliothèques de fonctions :
Collisions de noms entre le code que vous créez, les classes, fonctions
ou constantes internes de PHP, ou celle de bibliothèques tierces.
La capacité de faire des alias ou de raccourcir des Noms_Extremement_Long
pour aider à la résolution du premier problème, et améliorer la lisibilité
du code.
Les espaces de noms PHP fournissent un moyen pour regrouper des classes, interfaces,
fonctions ou constantes. Voici un exemple de syntaxe des espaces de noms PHP :
Exemple de syntaxe des espaces de noms
]]>
Les noms d'espaces de noms ne sont pas sensible à la casse.
Les espaces de noms PHP, mais aussi les noms composés
commençant par ces noms (comme PHP\Classes)
sont réservés pour l'utilisation interne du langage, et ne doivent pas être utilisés
dans le code de l'espace utilisateur.
Définition des espaces de noms
Bien que du code PHP valide puisse être contenu dans un espace de noms,
seuls les types de code suivants peuvent être affectés par les espaces de noms :
les classes (incluant les abstraites et les traits), les interfaces,
les fonctions et les constantes.
Les espaces de noms sont déclarés avec le mot-clé namespace.
Un fichier contenant un espace de noms doit déclarer l'espace au début
du fichier, avant tout autre code, avec une seule exception : le mot
clé .
Déclaration d'un espace de noms
]]>
Les nom complètement qualifié (c.à.d. les noms commençant avec un antislash)
ne sont pas autorisé dans les déclarations d'espaces de noms, car de telle
construction sont interprétées comme des expressions d'espace de nom
relatif.
Le seul élément autorisé avant la déclaration d'espace de noms est la commande
declare, pour définir l'encodage du fichier source. De plus,
aucun code non-PHP ne peut précéder la déclaration d'espace de noms, y compris
des espaces :
Erreur de déclaration d'un espace de noms
]]>
De plus, contrairement à d'autres structures PHP, le même espace de noms peut
être défini dans plusieurs fichiers, ce qui permet de scinder le contenu d'un
espace de noms sur plusieurs fichiers.
Déclaration d'un sous espace de noms
Comme pour les fichiers et les dossiers, les espaces de noms sont aussi
capables de spécifier une hiérarchie d'espaces de noms. Ainsi, un nom d'espace
de noms peut être défini avec ses sous-niveaux :
Déclaration d'un espace de noms avec hiérarchie
]]>
Dans l'exemple ci-dessus, la constante MonProjet\Sous\Niveau\CONNEXION_OK,
la classe MonProjet\Sous\Niveau\Connexion et la fonction
MonProjet\Sous\Niveau\connecte sont créées.
Définition de plusieurs espaces de noms dans le même fichier
Plusieurs espaces de noms peuvent aussi être déclarés dans le même fichier.
Il y a deux syntaxes autorisées.
Déclaration de plusieurs espaces de noms, syntaxe à combinaison simple
]]>
Cette syntaxe n'est pas recommandée pour combiner des espaces de noms
dans un seul fichier. Au lieu de cela, il est recommandé d'utiliser
la syntaxe à accolades.
Déclaration de plusieurs espaces de noms, syntaxe à accolades
]]>
Il est fortement recommandé, en tant que pratique de codage, de ne pas mélanger
plusieurs espaces de noms dans le même fichier. L'utilisation recommandée est de
combiner plusieurs scripts PHP dans le même fichier.
Pour combiner plusieurs codes sans espaces de noms dans du code avec espace de noms,
seule la syntaxe à accolades est supportée. Le code global doit être encadré par un
espace de noms sans nom, tel que celui-ci :
Déclaration de plusieurs espaces de noms avec un espace sans nom
]]>
Aucun code PHP ne peut exister hors des accolades de l'espace de noms,
sauf pour ouvrir une nouvelle instruction declare.
Déclaration de plusieurs espaces de noms avec un espace sans nom (2)
]]>
Utilisation des espaces de noms : introduction
Avant de discuter de l'utilisation des espaces de noms, il est important de
comprendre comment PHP devine quel espace de noms votre code utilise. Une
analogie simple peut être faite entre les espaces de noms de PHP et un système
de fichiers. Il y a trois moyens d'accéder à un fichier dans un système de
fichiers :
Un nom relatif de fichier, tel que foo.txt. Cela est résolu
en dossiercourant/foo.txt où dossiercourant est le
dossier de travail. Si le dossier courant est /home/foo,
ce nom se résout en /home/foo/foo.txt.
Un chemin relatif, tel que sous-dossier/foo.txt. Cela se
résout en dossiercourant/sous-dossier/foo.txt.
Un chemin absolu, tel que /main/foo.txt. Cela se résout
en /main/foo.txt.
Le même principe peut être appliqué aux espaces de noms de PHP.
Par exemple, on peut faire référence à une classe de trois manières :
Un nom sans qualificatif, ou une classe sans préfixe, telle que
$a = new foo(); ou
foo::methodestatique();. Si l'espace de noms courant
est espacedenomscourant, ceci se résout en
espacedenomscourant\foo. Si l'espace de noms est
global, soit encore l'espace de noms sans nom, cela devient foo.
Une mise en garde : les noms sans qualificatif pour les fonctions et les
constantes vont être pris dans l'espace de noms global, si la fonction
n'est pas définie dans l'espace de noms courant. Voyez
Utilisation des espaces de noms :
retour à l'espace de noms global pour les fonctions et les constantes pour
plus de détails.
Un nom qualifié, ou une classe préfixée telle que
$a = new sousespacedenoms\foo(); ou
sousespacedenoms\foo::methodestatique();. Si l'espace de noms courant
est espacedenomscourant, cela devient
espacedenomscourant\sousespacedenoms\foo. Si
le code est global, c'est à dire l'espace de noms sans nom,
cela devient sousespacedenoms\foo.
Un nom absolu, ou un nom préfixé avec un opérateur global tel que
$a = new \espacedenomscourant\foo(); ou
\espacedenomscourant\foo::methodestatique();. Cela fait toujours
référence au nom littéral spécifié dans le code : espacedenomscourant\foo.
Voici un exemple des trois syntaxes, dans du code réel :
file1.php
]]>
file2.php
]]>
Notez que pour accéder à n'importe quelle classe, fonction ou constante
globale, un nom absolu peut être utilisé, tel que
\strlen ou \Exception ou
\INI_ALL.
Accès aux classes, fonctions et constantes globales depuis un espace de noms
]]>
Espaces de noms et langage dynamique
L'implémentation des espaces de noms de PHP est influencée par sa nature dynamique
de langage de programmation. Par conséquent, pour convertir du code tel que le code
de l'exemple suivant, en un espace de noms :
Accès dynamique aux élémentsexample1.php:
]]>
Il faut utiliser un nom absolu (le nom de la classe, avec son préfixe d'espace
de noms). Notez qu'il n'y a pas de différence entre un nom absolu et un nom qualifié
dans un nom de classe, de fonction ou de constante dynamique, ce qui fait que l'antislash
initial n'est pas nécessaire.
Accès dynamique à des espaces de noms
]]>
Il est recommandé de lire la note au sujet
de la protection des espaces de noms dans les chaînes.
La commande namespace et la constante __NAMESPACE__
PHP supporte deux moyens pour accéder de manière abstraite aux éléments
dans l'espace de nom courant, à savoir la constante magique
__NAMESPACE__ et la commande namespace.
La valeur de __NAMESPACE__ est une chaîne qui contient le nom
de l'espace de noms courant. Dans l'espace global, sans nom, elle contient
une chaîne vide.
Exemple avec __NAMESPACE__, dans un code avec espace de noms
]]>
Exemple avec __NAMESPACE__, dans un code avec espace de noms global
]]>
La constante __NAMESPACE__ est utile pour construire
dynamiquement des noms, tels que :
Utilisation de __NAMESPACE__ pour une construction dynamique de noms
]]>
La commande namespace peut aussi être utilisée pour
demander explicitement un élément de l'espace de noms courant, ou d'un
sous-espace. C'est l'équivalent pour les espaces de noms de l'opérateur
self des classes.
l'opérateur namespace, dans un espace de noms
]]>
l'opérateur namespace, dans l'espace de noms global
]]>
Utilisation des espaces de noms : importation et alias
La capacité de faire référence à un nom absolu avec un alias ou en important
un espace de noms est stratégique. C'est un avantage similaire aux liens
symboliques dans un système de fichiers.
PHP peut aliaser(/importer) les constantes, fonctions, classes, interfaces,
et les espaces de noms.
Un alias est créé avec l'opérateur use.
Voici un exemple qui présente les cinq types d'importation :
importation et alias avec l'opérateur use
]]>
Notez que pour les noms avec chemin (les noms absolus contenant des
séparateurs d'espaces, tels que Foo\Bar, par comparaison avec
les noms globaux, tels que FooBar, qui n'en contiennent pas),
l'antislash initial n'est pas nécessaire et n'est pas recommandé, car les noms importés
doivent être absolus et ne sont pas résolus relativement à l'espace de noms courant.
De plus, PHP supporte des raccourcis pratiques, tels que les commandes use multiples.
importation et alias multiples avec l'opérateur use
]]>
L'importation est réalisée à la compilation, ce qui fait que cela n'affecte pas
les classes, fonctions et constantes dynamiques.
Importation et noms d'espaces dynamiques
]]>
De plus, l'importation n'affecte que les noms sans qualification. Les noms
absolus restent absolus, et inchangés par un import.
Importation et noms d'espaces absolus
]]>
Règles de contextes pour l'importation
Le mot-clé use doit être déclaré dans le contexte le plus
externe d'un fichier (le contexte global) ou alors dans les déclarations d'espace
de noms. Ceci car l'importation est effectuée à la compilation et non durant
l'éxecution, donc on ne peut empiler les contextes. L'exemple qui suit montre des
utilisation incorrectes du mot-clé use:
Règles d'importation incorrectes
]]>
Les règles d'importation sont basées sur les fichiers, ce qui signifie que les fichiers
inclus n'hériteront PAS des règles d'importation du fichier parent.
Déclaration du groupe use
Les classes, fonctions et constantes importées depuis
le même &namespace; peuvent être regroupées dans une
seule instruction &use.namespace;.
Espace de noms global
Sans aucune définition d'espace de noms, toutes les classes et les fonctions
sont placées dans l'espace de noms global : comme en PHP avant que les espaces
de noms aient été introduits. En préfixant un nom avec un antislash
\, on peut demander l'utilisation de l'espace de noms
global, même dans un contexte d'espace de noms spécifique.
Spécification d'espace de noms global
]]>
Utilisation des espaces de noms : retour à l'espace global
Dans un espace de noms, lorsque PHP rencontre un nom sans qualification,
que ce soit une classe, une fonction ou une constante, il le résout avec différentes
priorités. Les noms de classes sont toujours résolus avec l'espace de noms courant.
Pour accéder à des classes internes ou à des classes qui ne sont pas dans
un espace de noms, il faut les représenter avec leur nom absolu, tel que :
Accès aux classes globales depuis un espace de noms
]]>
Pour les fonctions et constantes, PHP va aller les chercher dans l'espace
global s'il ne peut les trouver dans l'espace de noms courant.
Accès aux fonctions et constantes globales dans un espace de noms
]]>
Règles de résolutions de noms
Dans le cadre des règles de résolution, il y a plusieurs définitions importantes :
Définitions pour les espaces de nomsnom non qualifié
Ceci est un identifiant ne contenant pas un séparateur d'espace de noms.
Par exemple : Foonom qualifié
Ceci est un identifiant contenant un séparateur d'espace de noms.
Par exemple : Foo\BarNom absolu
Ceci est un identifiant qui commence par un séparateur d'espace de noms.
Par exemple : \Foo\Bar. L'espace de noms Foo
est aussi un nom absolu.
Nom Relatif
C'est un identifiant commençant par namespace, tel que
namespace\Foo\Bar.
Les noms sont résolus en suivant les règles suivantes :
Les noms absolus se traduisent toujours par les noms sans le séparateur de namespace.
Par exemple, \A\B se traduit par A\B.
Tous les noms qui ne sont pas absolus sont traduit avec
le namespace remplacé par le namespace courant.
Si le nom apparait dans le namespace global, le préfixe
namespace\ est retiré. Par exemple namespace\A
dans le namespace X\Y se traduit par X\Y\A.
Le même nom dans le namespace global se traduit par A.
Pour les noms absolus, le premier segment est traduit
en accord avec la class/namespace de la table d'importation.
Par exemple, si le namespace A\B\C est importé comme C, le nom C\D\E est traduit par A\B\C\D\E.
Pour les noms absolus, si aucune règle d'import ne
s'applique, le namespace courant est préfixé par le nom.
Par exemple le nom C\D\E dans le namespace A\B,
est traduit par A\B\C\D\E.
Pour les noms absolus, le nom est traduit en lien avec la table courante d'importation pour le type de symbol respectif.
Cela signifie qu'un nom ressemblant à une classe est traduit en accord avec la table d'importation des
class/namespace, les noms de fonctions en utilisant la
table d'importation des fonctions, et les constantes en
utilisant la table d'importation des constantes.
Par exemple, après
use A\B\C; un usage tel que new C() correspond au nom
A\B\C(). De la même manière, après use function A\B\fn; un usage tel que fn() correspond au nom A\B\fn.
Pour les noms relatifs, si aucune règle ne s'applique, et que le nom
fait référence à une classe, le namespace courant sert de préfixe.
Par exemple new C() dans le namespace
A\B correspond au nom A\B\C.
pour les noms relatifs, si aucune règle ne s'applique, et que le nom
fait référence à une fonction ou une constante, et que le code est en
dehors du namespace global, the nom est résolu par l'exécution.
Supposons que le code est dans le namespace
A\B, voici comme un appel à la fonction foo() est résolu :
Il recherche une fonction dans l'espace de noms courant :
A\B\foo().
Il essaie de trouver et appeler la fonction globalefoo().
Exemples de résolutions d'espaces de noms
]]>
Foire aux questions : ce que vous devez savoir des espaces de noms
Cette FAQ est décomposée en deux sections : les questions courantes,
et les points particuliers de l'implémentation, qui peuvent être
utiles à la compréhension globale.
D'abord, les questions courantes.
Si je n'utilise pas d'espaces
de noms, est-ce que je dois m'en soucier ?
Comment utiliser une classe
globale ou interne depuis un espace de noms ?
Comment utiliser les classes
d'espaces de noms, les fonctions ou les constantes dans leur propre espace ?
Comment est-ce qu'un nom comme \mon\nom ou
\nom est résolu ?
Comment est-ce qu'un nom
tel que mon\nom est résolu ?
Comment un nom de classe
sans qualification, tel que nom, est résolu ?
Comment une fonction sans
qualification ou une constante de nom nom est résolue ?
Voici les points particuliers de l'implémentation, qui peuvent être
utiles à la compréhension globale.
Les noms importés ne doivent
pas entrer en conflit avec les classes définies dans le même fichier
Les espaces de noms imbriqués
sont interdits
Les noms d'espaces de noms
dynamiques doivent protéger l'antislash
Des constantes indéfinies
référencées avec un antislash produisent une erreur fatale
Impossible de remplacer
des constantes spéciales comme NULL, TRUE, FALSE, ZEND_THREAD_SAFE ou ZEND_DEBUG_BUILD
Si je n'utilise pas d'espaces de noms, est-ce que je dois m'en soucier ?
Non, les espaces de noms n'affectent pas le code existant, d'une
manière ou d'une autre, ni le code qui sera produit et qui n'utilise
pas les espaces de noms. Vous pouvez écrire ceci si vous voulez :
Accès à une classe globale de l'extérieur d'un espace de noms
]]>
C'est une fonctionnalité équivalente à :
Accéder à des classes globales hors d'un espace de noms
]]>
Comment utiliser une classe globale ou interne depuis un espace de noms ?Accès aux classes internes depuis un espace de noms
]]>
Comment utiliser les classes d'espaces de noms, les fonctions ou
les constantes dans leur propre espace ?
Accès aux classes, fonctions et constantes internes dans un espace de noms
]]>
Comment est-ce qu'un nom comme \mon\nom ou
\nom est résolu ?
Les noms qui commencent par \ sont toujours résolus en ce
à quoi ils ressemblent, ce qui fait que \mon\nom est en fait
mon\nom, et \Exception est
Exception.
Noms d'espaces absolus
]]>
Comment est-ce qu'un nom tel que mon\nom est résolu ?
Les noms qui contiennent un antislash mais ne commencent par par un
antislash, comme mon\nom peuvent être résolus de deux manières
différentes.
S'il y a eu une commande d'importation qui fait un alias de
mon, alors l'alias importé est appliqué à la place
de mon, et l'espace de noms devient mon\nom.
Sinon, l'espace de noms courant est ajouté avant le chemin de la classe
mon\nom.
Noms qualifiés
]]>
Comment un nom de classe
sans qualification, tel que nom, est résolu ?
Les noms de classes qui ne contiennent pas d'antislash comme
nom peuvent être résolus de deux manières différentes.
S'il y a une instruction d'importation qui définit un alias pour nom,
alors l'alias est appliqué.
Sinon, l'espace de noms courant est utilisé et préfixé à
nom.
Classes sans qualification
]]>
Comment une fonction sans qualification ou une constante
de nom nom est résolue ?
Les fonctions et constantes qui n'ont pas d'antislash dans leur nom
comme nom sont résolues de deux manières différentes :
D'abord, l'espace de noms courant est préfixé à nom.
Ensuite, si la constante ou la fonction nom n'existe pas
dans l'espace de nom courant, la version globale de la constante ou la
fonction nom est utilisée.
Fonctions et constantes sans espace de noms
]]>
Les noms importés ne doivent
pas entrer en conflit avec les classes définies dans le même fichier
La combinaison de scripts suivante est valide :
file1.php
]]>
another.php
]]>
file2.php
]]>
Il n'y a pas de conflit de noms, même si la classe MaClasse existe
dans l'espace de noms mes\trucs, car la définition de
MaClasse est dans un fichier séparé. Cependant, l'exemple
suivant produit une erreur fatale à cause d'un conflit de noms, car
MaClasse est définie dans le même fichier que l'instruction
use.
]]>
Les espaces de noms imbriqués sont interdits
PHP ne permet pas d'imbriquer des espaces de noms.
]]>
Cependant, il est facile de simuler des espaces de noms imbriqués,
comme ceci :
]]>
Les noms d'espaces de noms dynamiques doivent protéger l'antislash
Il est très important de réaliser que, comme les antislash sont utilisés comme
caractères de protection dans les chaînes, il faut toujours les doubler
pour pouvoir les utiliser dans une chaîne. Sinon, il y a un risque d'utilisation
inattendue :
Dangers de l'utilisation des espaces de noms dans une chaîne
]]>
Dans une chaîne à double guillemets, la séquence de protection est beaucoup plus
sécuritaire à utiliser, mais il est quand même recommandé de toujours protéger
les antislashs dans une chaîne qui contient un espace de noms.
Des constantes indéfinies référencées avec un antislash produisent une erreur fatale
Toute constante indéfinie qui est sans qualificatif telle que
FOO va produite une alerte : PHP supposait que
FOO était la valeur de la constante. Toute constante,
qualifiée partiellement ou totalement, qui contient un antislash,
produite une erreur fatale si indéfinie.
Constantes indéfinies
]]>
Impossible de remplacer des constantes spéciales comme NULL, TRUE, FALSE, ZEND_THREAD_SAFE ou ZEND_DEBUG_BUILD
Toute tentative dans un espace de noms de remplacer les constantes
natives ou spéciales, engendre une erreur fatale.
Constantes qui ne peuvent être redéfinies
]]>