L'espace de noms PHP (espace de noms) a été ajouté dans PHP 5.3 Si vous avez étudié C# et Java, l'espace de noms n'a rien de nouveau. Cependant, cela a toujours une importance très importante en PHP.
Les espaces de noms PHP peuvent résoudre les deux types de problèmes suivants :
Conflits de noms entre le code écrit par l'utilisateur et les classes/fonctions/constantes internes de PHP ou les classes/fonctions/constantes tierces.
Créez un nom alias (ou court) pour un nom d'identifiant très long (généralement défini pour atténuer le premier type de problème) afin d'améliorer la lisibilité du code source.
Par défaut, tous les noms de constantes, de classes et de fonctions sont placés dans l'espace global, tout comme avant les espaces de noms pris en charge par PHP.
Les espaces de noms sont déclarés à l'aide du mot-clé namespace. Si un fichier contient un espace de noms, il doit déclarer l'espace de noms avant tout autre code. Le format de syntaxe est le suivant :
<?php // Définir le code dans l'espace de noms 'MyProject' MyProject; // ... code...
Vous pouvez également définir différents codes d'espace de noms dans le même fichier, tels que :
<?php espace de noms MonProjet;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }espace de noms AnotherProject;const CONNECT_OK = 1;class Connection { /* .. . */ }fonction connecter() { /* ... */ }?>
Il n'est pas recommandé d'utiliser cette syntaxe pour définir plusieurs espaces de noms dans un seul fichier. Il est recommandé d’utiliser la forme de syntaxe suivante entre accolades.
<?phpnamespace MonProjet { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ }}namespace AnotherProject { const CONNECT_OK = 1; class Connection { /* .. . */ } fonction connecter() { /* ... */ }}?>
Pour combiner du code global sans espace de noms avec du code d'espace de noms, seule la syntaxe des accolades peut être utilisée. Le code global doit être entouré d'une instruction d'espace de noms sans nom suivie d'accolades, par exemple :
<?phpnamespace MonProjet {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }}namespace { // Code global session_start();$a = MonProjet connect();echo MonProjetConnection::start();}?>
Le seul code légal avant de déclarer un espace de noms est l'instruction declare qui définit l'encodage du fichier source. Tout code non PHP, y compris les espaces, ne peut pas apparaître avant une déclaration d'espace de noms.
<?phpdeclare(encoding='UTF-8'); //Définir plusieurs espaces de noms et espaces de noms de code non inclus dans l'espace de noms MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { / * ... */ }}espace de noms { // Code global session_start();$a = MyProjectconnect();echo MyProjectConnection::start();}?>
Le code suivant provoquera une erreur de syntaxe :
<html><?phpnamespace MyProject; // "<html>" apparaissant avant l'espace de noms provoquera une erreur fatale - l'espace de noms doit être la première instruction du script du programme ?>
Tout comme la relation entre répertoires et fichiers, les espaces de noms PHP vous permettent également de spécifier des noms d'espaces de noms hiérarchiques. Par conséquent, les noms d’espaces de noms peuvent être définis de manière hiérarchique :
<?phpnamespace MyProjectSubLevel; //Déclarer un espace de noms unique hiérarchique const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
L'exemple ci-dessus crée la constante MyProjectSubLevelCONNECT_OK, la classe MyProjectSubLevelConnection et la fonction MyProjectSubLevelConnect.
Les noms de classe dans l'espace de noms PHP peuvent être référencés de trois manières :
Un nom non qualifié ou un nom de classe sans préfixe, tel que $a=new foo(); ou foo::staticmethod();. Si l'espace de noms actuel est currentnamespace, foo sera résolu en currentnamespacefoo. Si le code utilisant foo est global et ne contient de code dans aucun espace de noms, alors foo sera résolu comme foo. Avertissement : Si une fonction ou une constante dans un espace de noms n'est pas définie, la fonction ou le nom de constante non qualifié est résolu en une fonction globale ou un nom de constante.
Un nom qualifié ou un nom qui inclut un préfixe, tel que $a = new subnamespacefoo(); ou subnamespacefoo::staticmethod();. Si l'espace de noms actuel est currentnamespace, foo sera résolu en currentnamespacesubnamespacefoo. Si le code utilisant foo est global, code non contenu dans aucun espace de noms, foo sera résolu en sous-espace de nomsfoo.
Un nom complet ou un nom qui inclut un opérateur de préfixe global, par exemple $a = new currentnamespacefoo(); ou currentnamespacefoo::staticmethod();. Dans ce cas, foo est toujours résolu en nom littéral currentnamespacefoo dans le code.
Voici un exemple d’utilisation de ces trois méthodes :
code du fichier file1.php
<?phpnamespace FooBarsubnamespace; const FOO = 1;function foo() {}class foo{ static function staticmethod() {}}?>
code du fichier file2.php
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* Nom non qualifié*/foo(); est la fonction FooBarfoofoo::staticmethod(); // Elle est analysée dans la classe FooBarfoo et la méthode est staticmethodecho FOO; Résout en constante FooBarFOO/* nom qualifié*/subnamespacefoo(); // Résout en fonction FooBarsubnamespacefoosubnamespacefoo::staticmethod(); // Résout en classe FooBarsubnamespace foo, // et méthodes de classe staticmethodecho subnamespaceFOO; // analysé en constante FooBarsubnamespaceFOO /* Nom complet */FooBarfoo(); // Résout la fonction FooBarfooFooBarfoo::staticmethod(); // Résout la classe FooBarfoo et la classe Méthode staticmethodecho FooBarFOO; //Résolu comme constante FooBarFOO?>
Notez que pour accéder à n'importe quelle classe, fonction ou constante globale, vous pouvez utiliser un nom complet, tel que strlen() ou Exception ou INI_ALL.
Accédez aux classes, fonctions et constantes globales dans un espace de noms :
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // Appel de la fonction globale strlen$b = INI_ALL; // Accès à la constante globale INI_ALL$ c = new Exception('error'); // Instancier la classe globale Exception ?>
L'implémentation des espaces de noms PHP est affectée par la nature dynamique du langage lui-même. Donc, si vous souhaitez convertir le code ci-dessous en espace de noms, accédez aux éléments de manière dynamique.
Code du fichier exemple1.php :
<?phpclass classname{ function __construct() { echo __METHOD__,"n"; }}function funcname(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'classname';$obj = new $a; // imprime le nom de la classe ::__construct$b = 'funcname';$b(); // imprime le nom de la fonctionecho constant('constname'), "n"; // affiche global ?>
Vous devez utiliser un nom complet (le nom de la classe incluant le préfixe de l'espace de noms). Notez que la barre oblique inverse n'est pas nécessaire car il n'y a aucune différence entre les noms qualifiés et complets dans les noms de classes dynamiques, les noms de fonctions ou les noms de constantes.
Accéder dynamiquement aux éléments d'un espace de noms
<?phpnamespace namespacename;class classname{ function __construct() { echo __METHOD__,"n"; }}function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";include 'example1.php' ;$a = 'nom de classe';$obj = new $a; // Nom de classe de sortie ::__construct$b = 'funcname';$b(); // Nom de la fonction de sortie echo constant('constname'), "n"; // Sortie globale/* Si des guillemets doubles sont utilisés, la méthode d'utilisation est "\namespacename\classname "* /$a = 'namespacenameclassname';$obj = new $a; // Sortie namespacenameclassname::__construct$a = 'namespacenameclassname';$obj = new $a; // Nom de l'espace de noms de sortienom de classe ::__construct$b = 'nom de l'espace de nomsnom de la fonction';$b(); // Nom de l'espace de noms de sortienom de la fonction$b = 'nom de l'espace de nomsnom de la fonction';$b(); // Nom de l'espace de noms de sortienom de la fonctionecho constant( 'namespacenameconstname'), "n"; // Constante de namespacedecho de sortie ('namespacenameconstname'), "n"; Espace de noms de sortie ?>
PHP prend en charge deux méthodes abstraites pour accéder aux éléments dans l'espace de noms actuel, la constante magique __NAMESPACE__ et le mot-clé namespace.
La valeur de la constante __NAMESPACE__ est une chaîne contenant le nom de l'espace de noms actuel. Dans le code global, non inclus dans aucun espace de noms, il contient une chaîne vide.
Exemple __NAMESPACE__, code dans un espace de noms
<?phpnamespace MonProjet;echo '"', __NAMESPACE__, '"'; // Sortie "MonProjet"?>
Exemple __NAMESPACE__, code global
<?phpecho '"', __NAMESPACE__, '"'; // Sortie ""?>
La constante __NAMESPACE__ est utile lors de la création dynamique de noms, par exemple :
Créez des noms dynamiquement à l'aide de __NAMESPACE__
<?phpnamespace MyProject;function get($classname){ $a = __NAMESPACE__ '\' .
Le mot clé espace de noms peut être utilisé pour accéder explicitement aux éléments de l'espace de noms ou des sous-espaces de noms actuels. C'est l'équivalent de l'auto-opérateur en classe.
opérateur d'espace de noms, code dans l'espace de noms
<?phpnamespace MyProject;utilise blahblah comme mien ; // voir "Utilisation des espaces de noms : importation/alias"blahmine(); // appelle la fonction blahblahmine()namespaceblahmine( //); appelle la fonction MyProjectblahmine()namespacefunc(); // appelle la fonction MyProjectfunc()namespacesubfunc(); MyProjectsubfunc()namespacecname::method(); // appelle la méthode statique "méthode" de la classe MyProjectcname$a = new namespacesubcname(); // instancie l'objet de la classe MyProjectsub cname$b = namespaceCONSTANT; // attribue la valeur de la constante MyProjectCONSTANT à $b ?>
opérateur d'espace de noms, code global
<?phpnamespacefunc(); // appelle la fonction func()namespacesubfunc(); // appelle la fonction subfunc()namespacecname::method(); // appelle la méthode statique "méthode" de class cname$a = new namespacesubcname(); // instancie l'objet de la classe subcname$b = namespaceCONSTANT; // attribue la valeur de la constante CONSTANT à $b?>
La prise en charge des espaces de noms PHP propose deux manières d'utiliser les alias ou les importations : en utilisant des alias pour les noms de classe ou en utilisant des alias pour les noms d'espace de noms.
En PHP, l'alias est implémenté via l'opérateur use. Voici un exemple utilisant les trois méthodes d'importation possibles :
1. Utilisez l'opérateur use pour importer/utiliser des alias
<?phpnamespace foo;use MyFullClassname as Another;// L'exemple suivant est le même que use MyFullNSname as NSname use MyFullNSname;// Importer une classe globale use ArrayObject;$obj = new namespaceAnother; // Instancie l'objet fooAnother $obj = new Another; // Instancie l'objet MyFullClassname NSnamesubnsfunc( //); Appelez la fonction MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // Instancier l'objet ArrayObject // Si "use ArrayObject" n'est pas utilisé, instancier un objet fooArrayObject ?>
2. Une ligne contient plusieurs instructions d'utilisation
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instancier l'objet MyFullClassname NSnamesubnsfunc(); // Appeler la fonction MyFullNSname sous-titresfunc?>
Les opérations d'importation sont effectuées lors de la compilation, mais pas les noms de classes dynamiques, les noms de fonctions ou les noms de constantes.
3. Importation et noms dynamiques
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instancier un objet MyFullClassname $a = 'Another';$obj = new $a; un Un autre objet ?>
De plus, l’opération d’importation affecte uniquement les noms non qualifiés et qualifiés. Les noms pleinement qualifiés ne sont pas affectés par les importations car ils sont déterministes.
4. Importation et noms complets
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instancier la classe MyFullClassname $obj = new Another; // Instancier une autre classe $obj = new Another thing; // Instancier ma classeFullClassnamething $obj = new Anotherthing; // Instancier une autre classething?>
Dans un espace de noms, lorsque PHP rencontre un nom de classe, de fonction ou de constante non qualifié, il utilise une stratégie de priorité différente pour résoudre le nom. Les noms de classe sont toujours résolus en noms dans l'espace de noms actuel. Par conséquent, lorsque vous accédez à des noms de classe internes au système ou non contenus dans l'espace de noms, vous devez utiliser le nom complet, par exemple :
1. Accédez aux classes globales dans l'espace de noms
<?phpnamespace ABC;class Exception extends Exception {}$a = new Exception('hi'); // $a est un objet de classe ABCException $b = new Exception( 'hi'); // $b est un objet de classe Exception $c = new ArrayObject; // Erreur fatale, classe ABCArrayObject introuvable ?>
Pour les fonctions et les constantes, si la fonction ou la constante n'existe pas dans l'espace de noms actuel, PHP utilisera la fonction ou la constante dans l'espace global.
2. Sauvegardez les fonctions/constantes globales dans l'espace de noms
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n"; // Sortie "45"echo INI_ALL, " n"; // Sortie "7" - utilise la constante globale INI_ALLecho strlen('hi'), "n"; // Sortie "2"if (is_array('hi')) { // Sortie "n'est pas un tableau" echo "est un tableaun";} else { echo "n'est pas un tableaun";}?>
Si aucun espace de noms n'est défini, toutes les classes et fonctions sont définies dans l'espace global, tout comme avant que PHP n'introduise le concept d'espace de noms. Préfixer un nom avec indique que le nom se trouve dans l'espace global, même s'il se trouve dans un autre espace de noms.
Utiliser les instructions spatiales globales
<?phpnamespace ABC;/* Cette fonction est ABCfopen */function fopen() { /* ... */ $f = fopen(...); La fonction fopen renvoie $f;} ?>
Depuis l'émergence des espaces de noms, la chose la plus sujette aux erreurs est lors de l'utilisation d'une classe, quel est le chemin de recherche pour cette classe.
<?phpnamespace A;use BD, CE as F;// Function call foo(); // Essayez d'abord d'appeler la fonction foo() définie dans l'espace de noms "A" // Ensuite essayez d'appeler le global function" foo"foo(); // Appelez la fonction spatiale globale "foo" myfoo(); // Appelez la fonction "foo" définie dans l'espace de noms "Amy" F( //); Essayez d'abord d'appeler la fonction "F" définie dans l'espace de noms "A" // Essayez ensuite d'appeler la fonction globale "F" // Référence de classe new B(); // Créez la classe "B" définie dans l'espace de noms "A" Un objet de class "AB" new D(); // S'il n'est pas trouvé, essayez de charger automatiquement la classe "AB" new D(); // À l'aide des règles d'importation, créez un objet de classe "D" défini dans l'espace de noms "B" " // Si introuvable S'il est trouvé, essayez de charger automatiquement la classe "BD" new F(); // À l'aide des règles d'importation, créez un objet de classe "E" défini dans l'espace de noms "C" // S'il n'est pas trouvé, essayez de charger automatiquement la classe "CE" new B(); de la classe "B" définie dans l'espace global // S'il n'est pas trouvé, essayez de charger automatiquement la classe "B" new D(); // Crée un objet de classe "D" défini dans l'espace global // S'il n'est pas trouvé, essayez de classe de chargement automatique "D" nouveau F(); // Crée un objet de classe "F" défini dans l'espace global // S'il n'est pas trouvé, essayez de charger automatiquement la classe "F" // Appelez une méthode statique ou une fonction d'espace de noms dans un autre espace de noms Bfoo() ; // Appel de la fonction "foo" dans l'espace de noms "AB" B::foo(); // Appel de la méthode "foo" de la classe "B" définie dans l'espace de noms "A" // Si la classe "AB" est pas trouvé , puis essayez de charger automatiquement la classe "AB" D::foo(); // Utiliser les règles d'importation pour appeler la méthode "foo" de la classe "D" définie dans l'espace de noms "B" // Si la classe "BD " " S'il n'est pas trouvé, essayez de charger automatiquement la classe "BD"Bfoo(); // Appelez la fonction "foo" dans l'espace de noms "B" B::foo(); fonction dans l'espace global Classe "B" La méthode "foo" // Si la classe "B" n'est pas trouvée, essayez de charger automatiquement la classe "B" // Une méthode ou une fonction statique dans l'espace de noms actuel AB::foo(); // Appelez l'espace de noms "A" Méthode "foo" de la classe "B" définie dans A" // Si la classe "AAB" n'est pas trouvée, essayez de charger automatiquement la classe "AAB"AB::foo() ; // Appelez la méthode "foo" de la classe "B" définie dans l'espace de noms "A" // Si la classe "AB" n'est pas trouvée, essayez de charger automatiquement la classe "AB" ?>
La résolution de noms suit les règles suivantes :
Les appels aux noms complets de fonctions, classes et constantes sont résolus au moment de la compilation. Par exemple, le nouveau AB est résolu en classe AB .
Tous les noms non qualifiés et les noms qualifiés (noms non pleinement qualifiés) sont convertis au moment de la compilation conformément aux règles d'importation en vigueur. Par exemple, si l'espace de noms ABC était importé en tant que C , alors les appels à CDe() seraient traduits en ABCDe() .
Dans un espace de noms, tous les noms qualifiés qui ne sont pas convertis conformément aux règles d'importation auront le nom de l'espace de noms actuel ajouté en préfixe. Par exemple, si CDe() est appelé dans l'espace de noms AB , CDe() sera converti en ABCDe() .
Les noms de classe non qualifiés sont convertis au moment de la compilation selon les règles d'importation actuelles (les noms complets sont utilisés à la place des noms d'importation courts). Par exemple, si l'espace de noms ABC est importé en tant que C, new C() est converti en new ABC() .
Dans un espace de noms (par exemple AB), les appels de fonction vers des noms non qualifiés sont résolus au moment de l'exécution. Par exemple, un appel à la fonction foo() est analysé comme ceci :
Rechercher une fonction nommée ABfoo() dans l'espace de noms actuel
Essayez de trouver et d'appeler la fonction foo() dans l'espace global .
Les appels à des noms non qualifiés ou à des classes de noms qualifiés (noms non pleinement qualifiés) dans un espace de noms (par exemple AB ) sont résolus au moment de l'exécution. Voici le processus d'analyse d'appel de new C() et new DE() : Analyse de new C() :
Recherchez les classes ABC dans l'espace de noms actuel.
Essayez de charger automatiquement les classes ABC .
Analyse du nouveau DE() :Ajoutez le nom de la classe avec le nom de l'espace de noms actuel pour devenir : ABDE , puis recherchez la classe.
Essayez de charger automatiquement la classe ABDE .
Afin de faire référence à une classe globale dans l'espace de noms global, le nom complet new C() doit être utilisé.