Espace de noms PHP
L'espace de noms PHP (espace de noms) a été ajouté dans PHP 5.3 Si vous avez étudié le C# et Java, alors l'espace de noms n'a rien de nouveau. Cependant, cela a toujours une importance très importante en PHP.
L'espace de noms PHP peut résoudre les deux types de problèmes suivants :
Code écrit par les utilisateurs et les classes/fonctions/constantes internes PHP ou les classes/fonctions/constantes tierces conflit de nom.
Créer 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), améliorant ainsi la lisibilité du code source.
Définition des espaces de noms
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.
Pour nommer l'espace, nous utilisons généralement le nom ou l'abréviation de l'entreprise, de l'entreprise ou de l'individu comme identifiant. La première lettre doit être en majuscule et ne peut pas commencer par un chiffre. L'espace de noms est identifié par l'instruction namespace du mot-clé. 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// Le code est défini dans l'espace de noms 'MonProjet'
espace de noms MonProjet
// . .. code. ..
?>
Vous pouvez également définir différents codes d'espace de noms dans le même fichier, tels que :
espace de noms MonProjet1;
// Code PHP dans l'espace de noms MonProjet1
espace de noms MonProjet2
// Code PHP dans l'espace de noms MonProjet2
// Une autre syntaxe
namespace MyProject3 {
// Code PHP dans l'espace de noms MyProject3
}
?>
La seule code 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 doit pas apparaître avant une déclaration d'espace de noms.
<?php declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码 namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // 全局代码 session_start(); $a = MyProject\connect(); echo MyProject\Connection::start(); } ?>
Le code suivant aura une erreur de syntaxe :
<html>
<?php
namespace MyProject; // "< apparaît avant le namespace html>" provoquera une erreur fatale - l'espace de noms doit être la première instruction du script du programme
?>
sous-espace de noms
La déclaration du sous-espace de noms est exactement la même chose que l'exemple précédent. La seule différence est que nous ajoutons un symbole pour séparer l'espace de noms et le sous-espace de noms. Le sous-espace de noms peut être divisé en n'importe quel niveau, à condition qu'il puisse être clairement divisé par fonction :
<?php
.namespace MyProjectSubLevel; //Déclarer un espace de noms hiérarchique unique
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 :
Nom non qualifié ou 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, foo sera résolu comme foo. Avertissement : Si une fonction ou une constante dans l'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.
Nom qualifié, ou nom incluant 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 subnamespacefoo.
Nom complet ou 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.
Ce qui suit est un exemple d'utilisation de ces trois méthodes :
code de fichier file1.php
<?php namespace Foo\Bar\subnamespace; const FOO = 1; function foo() {} class foo { static function staticmethod() {} } ?>
code de fichier file2.php
<?php namespace Foo\Bar; include 'file1.php'; const FOO = 2; function foo() {} class foo { static function staticmethod() {} } /* 非限定名称 */ foo(); // 解析为 Foo\Bar\foo resolves to function Foo\Bar\foo foo::staticmethod(); // 解析为类 Foo\Bar\foo的静态方法staticmethod。resolves to class Foo\Bar\foo, method staticmethod echo FOO; // resolves to constant Foo\Bar\FOO /* 限定名称 */ subnamespace\foo(); // 解析为函数 Foo\Bar\subnamespace\foo subnamespace\foo::staticmethod(); // 解析为类 Foo\Bar\subnamespace\foo, // 以及类的方法 staticmethod echo subnamespace\FOO; // 解析为常量 Foo\Bar\subnamespace\FOO /* 完全限定名称 */ \Foo\Bar\foo(); // 解析为函数 Foo\Bar\foo \Foo\Bar\foo::staticmethod(); // 解析为类 Foo\Bar\foo, 以及类的方法 staticmethod echo \Foo\Bar\FOO; // 解析为常量 Foo\Bar\FOO ?>
Attention à accéder à toutes les classes, fonctions ou constantes globales peut utiliser des noms complets, tels que strlen() ou Exception ou INI_ALL.
Accéder aux classes, fonctions et constantes globales à l'intérieur d'un espace de noms :
<?php namespace Foo; function strlen() {} const INI_ALL = 3; class Exception {} $a = \strlen('hi'); // 调用全局函数strlen $b = \INI_ALL; // 访问全局常量 INI_ALL $c = new \Exception('error'); // 实例化全局类 Exception ?>
Espaces de noms et fonctionnalités de langage dynamiques
L'implémentation des espaces de noms PHP est affectée par The influence des caractéristiques dynamiques de la langue elle-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 de fichier exemple1.php :
<?php class classname { function __construct() { echo __METHOD__,"\n"; } } function funcname() { echo __FUNCTION__,"\n"; } const constname = "global"; $a = 'classname'; $obj = new $a; // prints classname::__construct $b = 'funcname'; $b(); // prints funcname echo constant('constname'), "\n"; // prints global ?>
Doit utiliser un nom complet (nom de classe incluant le préfixe d'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ès dynamique aux éléments de l'espace de noms
<?php namespace namespacename; class classname { function __construct() { echo __METHOD__,"\n"; } } function funcname() { echo __FUNCTION__,"\n"; } const constname = "namespaced"; include 'example1.php'; $a = 'classname'; $obj = new $a; // prints classname::__construct $b = 'funcname'; $b(); // prints funcname echo constant('constname'), "\n"; // prints global /* note that if using double quotes, " \namespacename\classname" must be used */ $a = '\namespacename\classname'; $obj = new $a; // prints namespacename\classname::__construct $a = 'namespacename\classname'; $obj = new $a; // also prints namespacename\classname::__construct $b = 'namespacename\funcname'; $b(); // prints namespacename\funcname $b = '\namespacename\funcname'; $b(); // also prints namespacename\funcname echo constant('\namespacename\constname'), "\n"; // prints namespaced echo constant('namespacename\constname'), "\n"; // also prints namespaced ?>
mot-clé de l'espace de noms et constante __NAMESPACE__
PHP prend en charge deux abstractions pour accéder aux éléments internes des méthodes Element de l'espace de noms actuelles, Constante magique __NAMESPACE__ et mot-clé d'espace de noms.
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.
__NAMESPACE__ exemple, code dans l'espace de noms
<?php
espace de noms MyProject;
echo '"' , __NAMESPACE__, '"'; // Sortie "MonProjet"
?>
__NAMESPACE__ exemple, code global
<?php
echo '"', __NAMESPACE__, '"'; // Output ""
?>
La constante __NAMESPACE__ est utile lors de la création dynamique de noms, par exemple :
Créez des noms dynamiquement en utilisant __NAMESPACE__
<?php
namespace MonProjet;
function get($classname)
{
$a = '\' $classname; return new $a;
}
?>
<?php namespace MyProject; use blah\blah as mine; // see "Using namespaces: importing/aliasing" blah\mine(); // calls function blah\blah\mine() namespace\blah\mine(); // calls function MyProject\blah\mine() namespace\func(); // calls function MyProject\func() namespace\sub\func(); // calls function MyProject\sub\func() namespace\cname::method(); // calls static method "method" of class MyProject\cname $a = new namespace\sub\cname(); // instantiates object of class MyProject\sub\cname $b = namespace\CONSTANT; // assigns value of constant MyProject\CONSTANT to $b ?>opérateur d'espace de noms, code global
<?php namespace\func(); // calls function func() namespace\sub\func(); // calls function sub\func() namespace\cname::method(); // calls static method "method" of class cname $a = new namespace\sub\cname(); // instantiates object of class sub\cname $b = namespace\CONSTANT; // assigns value of constant CONSTANT to $b ?>
Utiliser l'espace de noms : alias/import
PHP L'espace de noms prend en charge 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. Notez que PHP ne prend pas en charge les fonctions ou constantes importées. En PHP, les alias sont implémentés via l'opérateur use. Voici un exemple d'utilisation des trois méthodes d'importation possibles : 1. Utilisez l'opérateur use pour importer/utiliser des alias.
<?php namespace foo; use My\Full\Classname as Another; // 下面的例子与 use My\Full\NSname as NSname 相同 use My\Full\NSname; // 导入一个全局类 use \ArrayObject; $obj = new namespace\Another; // 实例化 foo\Another 对象 $obj = new Another; // 实例化 My\Full\Classname 对象 NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func $a = new ArrayObject(array(1)); // 实例化 ArrayObject 对象 // 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象 ?>2. Une ligne contient plusieurs instructions d'utilisation
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // 实例化 My\Full\Classname 对象 NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func ?>L'opération d'importation est exécutée lors de la compilation, mais le nom de la classe dynamique, le nom de la fonction ou le nom de la constante ne l'est pas. 3. Import et noms dynamiques
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // 实例化一个 My\Full\Classname 对象 $a = 'Another'; $obj = new $a; // 实际化一个 Another 对象 ?>De plus, l'opération d'import n'affecte que les noms non qualifiés et les noms qualifiés. Les noms pleinement qualifiés ne sont pas affectés par les importations car ils sont déterministes. 4. Importer et nom complet
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // 实例化对象的类 My\Full\Classname $obj = new \Another; // instantiates object of class Another $obj = new Another\thing; // 实例化对象的类 My\Full\Classname\thing $obj = new \Another\thing; // instantiates object of class Another\thing ?>utiliser l'utilisation du mot-clé : doit être en haut du fichier PHP, c'est-à-dire la balise d'ouverture de PHP < ?php ou La déclaration d'espace de noms est suivie du mot-clé use pour importer le code. Lorsque vous utilisez le mot-clé use pour importer du code, il n'est pas nécessaire d'ajouter un symbole au début du nom de la classe, car PHP suppose que l'espace de noms importé est entièrement qualifié. Le mot-clé use doit être utilisé dans la portée globale (c'est-à-dire qu'il ne peut pas être utilisé dans une classe ou une fonction) Le mot-clé use peut être placé sous la déclaration d'espace de noms, en utilisant pour importer code dans d’autres espaces de noms.
Utilisation d'espaces de noms : fonctions/constantes globales de secours
Dans un espace de noms, lorsque PHP rencontre une classe, une fonction ou un nom 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 à l'intérieur du système ou non inclus dans l'espace de noms, vous devez utiliser des noms complets, par exemple : 1. Accédez aux classes globales dans l'espace de noms<?php namespace A\B\C; class Exception extends \Exception {} $a = new Exception('hi'); // $a 是类 A\B\C\Exception 的一个对象 $b = new \Exception('hi'); // $b 是类 Exception 的一个对象 $c = new ArrayObject; // 致命错误, 找不到 A\B\C\ArrayObject 类 ?>Pour les fonctions et Pour les constantes, si la fonction ou la constante n'existe pas dans l'espace de noms actuel, PHP reviendra à utiliser la fonction ou la constante dans l'espace global. 2. Sauvegardez les fonctions/constantes globales dans l'espace de noms
<?php namespace A\B\C; const E_ERROR = 45; function strlen($str) { return \strlen($str) - 1; } echo E_ERROR, "\n"; // 输出 "45" echo INI_ALL, "\n"; // 输出 "7" - 使用全局常量 INI_ALL echo strlen('hi'), "\n"; // 输出 "1" if (is_array('hi')) { // 输出 "is not array" echo "is array\n"; } else { echo "is not array\n"; } ?>Espace global Si aucun espace de noms n'est défini, toutes les classes et fonctions sont définies globalement dans l'espace, comme c'était le cas auparavant. PHP a introduit le concept d'espaces de noms. Le préfixe d'un nom indique que le nom se trouve dans l'espace global, même s'il se trouve dans un autre espace de noms. Instructions pour utiliser l'espace globalPour utiliser l'espace de noms global, il vous suffit d'ajouter un symbole avant le nom de la classe. Par exemple : throw new Exception();
<?php namespace A\B\C; /* 这个函数是 A\B\C\fopen */ function fopen() { /* ... */ $f = \fopen(...); // 调用全局的fopen函数 return $f; ?><🎜. >L'ordre de l'espace de noms
Depuis l'introduction 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.
<?php
espace de noms A ;
utiliser BD, CE comme F
// Appel de fonction
foo( /); / Essayez d'abord d'appeler la fonction foo() définie dans l'espace de noms "A"
// Essayez ensuite d'appeler la fonction globale "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 définie dans l'espace de noms " A" F"
// Essayez d'appeler à nouveau la fonction globale "F"
// Référence de classe
new B(); // Créez l'espace de noms défini dans espace de noms "A" Un objet de classe "B"
// S'il n'est pas trouvé, essayez de charger automatiquement la classe "AB"
new D(); // Utilisez les règles d'importation pour créer un objet défini dans l'espace de noms "B" Un objet de classe "D"
// S'il n'est pas trouvé, essayez de charger automatiquement la classe "BD"
new F(); // Utiliser les règles d'importation pour créer un objet défini dans l'espace de noms " C" Un objet de classe "E"
// S'il n'est pas trouvé, essayez de charger automatiquement la classe "CE"
new B(); // Crée un objet de classe "B" défini dans le global space Object
// 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 charger automatiquement la classe "D"
new F(); // Crée un objet de classe "F" défini dans l'espace global
// S'il n'est pas trouvé, essayez la classe Autoload "F"
// Appeler une méthode statique ou une fonction d'espace de noms dans un autre espace de noms
Bfoo(); // Appeler la fonction "foo" dans l'espace de noms "AB"
B ::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 la charger automatiquement 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 " Si elle n'est pas trouvée, essayez de charger automatiquement la classe "BD"
Bfoo(); // Appeler la fonction "foo" dans l'espace de noms "B"
B::foo(); " méthode de classe "B" dans l'espace global
// Si la classe "B" n'est pas trouvée, essayez de charger automatiquement la classe "B"
// Statique dans l'espace de noms actuel Méthode ou fonction
AB::foo(); // Appelez la méthode "foo" de la classe "B" définie dans l'espace de noms "AA"
// 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 "AB"
// 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 :
1 Les appels aux fonctions, classes et constantes avec des noms complets sont résolus au moment de la compilation. Par exemple, le nouveau AB se résout en classe AB.
2. Tous les noms non qualifiés et les noms qualifiés (noms non pleinement qualifiés) sont convertis au moment de la compilation selon les 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 convertis en ABCDe().
3. Au sein de l'espace de noms, tous les noms qualifiés qui ne sont pas convertis selon les règles d'importation seront précédés du nom de l'espace de noms actuel. Par exemple, si CDe() est appelé dans l'espace de noms AB, CDe() sera converti en ABCDe().
4. 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, alors new C() est converti en new ABC() .
5. 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 :
Trouver une fonction nommée ABfoo() dans l'espace de noms actuel
Essayer de trouver et d'appeler une fonction dans l'espace global foo ().
6. 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() : Analyse de new DE() : Afin de faire référence à la classe globale dans l'espace de noms global, le nom complet new C() doit être utilisé.
Ajoutez le nom de l'espace de noms actuel devant le nom de la classe pour devenir : ABDE, puis recherchez la classe.
Essayez de charger automatiquement la classe ABDE.
Recherchez la classe ABC dans l'espace de noms actuel.
Essayez de charger automatiquement la classe ABC.