Les espaces de noms Introduction 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éments example1.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 <literal>use</literal> 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 noms nom non qualifié Ceci est un identifiant ne contenant pas un séparateur d'espace de noms. Par exemple : Foo nom qualifié Ceci est un identifiant contenant un séparateur d'espace de noms. Par exemple : Foo\Bar Nom 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 globale foo(). 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 <literal>\mon\nom</literal> ou <literal>\nom</literal> 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 <literal>mon\nom</literal> 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 <literal>nom</literal>, 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 <literal>nom</literal> 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 ]]>