Espace de noms PHP (espace de noms)
L'espace de noms PHP (espace de noms) a été ajouté dans PHP 5.3
Qu'est-ce qu'un espace de noms?? D'une manière générale, un espace de noms est une fa?on d'encapsuler des choses. Ce concept abstrait se retrouve à de nombreux endroits. Par exemple, dans le système d'exploitation, les répertoires
sont utilisés pour regrouper les fichiers associés. Pour les fichiers du répertoire, il joue le r?le d'un espace de noms. Par exemple, le fichier foo.txt peut exister dans les répertoires /home/greg et /home/other en même temps, mais deux fichiers foo.txt ne peuvent pas exister dans le même répertoire. De plus, lors de l'accès au fichier
foo.txt en dehors du répertoire /home/greg, nous devons mettre le nom du répertoire et le séparateur de répertoire avant le nom du fichier pour obtenir /home/greg/foo.txt. Ce principe appliqué au domaine de la programmation est le concept d'espace de noms
.
L'espace de noms PHP peut résoudre les deux types de problèmes suivants?: 1. et Conflits de noms entre les classes/fonctions/constantes internes de PHP ou les classes/fonctions/constantes tierces.
2. Créez un nom d'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.
Définir l'espace de noms Par défaut, toutes les constantes, classes et fonctions les noms sont placés dans l'espace global, tout comme avant les espaces de noms pris en charge par PHP.
Un espace de noms est déclaré à 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.
La syntaxe est la suivante?: <?php
// 定義代碼在 'MyProject' 命名空間中
namespace MyProject;
// ... 代碼 ...
?>
你也可以在同一個文件中定義不同的命名空間代碼,如:
<?php
namespace MyProject1;
// MyProject1 命名空間中的PHP代碼
namespace MyProject2;
// MyProject2 命名空間中的PHP代碼
// 另一種語法
namespace MyProject3 {
// MyProject3 命名空間中的PHP代碼
}
?>
Le seul code légal avant de déclarer un espace de noms est l'instruction declare qui définit comment le fichier source est codé. De plus, tout code non PHP incluant des caractères d'espacement ne peut pas appara?tre avant la déclaration de l'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(); } ?>
et le code suivant signalera une erreur
<html> <?php namespace MyProject; // 命名空間前出現(xiàn)了“<html>” 會致命錯誤 - 命名空間必須是程序腳本的第一條語句 ?>
Le L'espace de noms est très similaire à la relation entre les répertoires et les fichiers. Les espaces de noms PHP vous permettent également de spécifier des noms d'espace de noms hiérarchiques. Par conséquent, les noms d'espaces de noms peuvent être définis de manière hiérarchique?:
<?php namespace MyProject\Sub\Level; //聲明分層次的單個命名空間 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.
Utilisation de l'espace de noms Avant de discuter de la fa?on d'utiliser les espaces de noms, vous devez comprendre comment PHP sait quels éléments d'espace de noms utiliser. Une analogie simple peut être faite entre l'espace de noms PHP et le système de fichiers. Il existe trois fa?ons d'accéder à un fichier dans le système de fichiers?: 1. Format de nom de fichier relatif tel que foo.txt. Il sera analysé comme currentdirectory/foo.txt, où currentdirectory représente le répertoire actuel. Ainsi, si le répertoire actuel est /home/foo, le nom de fichier est résolu en /home/foo/foo.txt. 2. Le nom du chemin relatif est sous la forme de sous-répertoire/foo.txt. Il sera analysé comme currentdirectory/subdirectory/foo.txt. ? ? 3. Le nom du chemin absolu est sous la forme /main/foo.txt. Il sera analysé comme /main/foo.txt. Les éléments de l'espace de noms PHP utilisent le même principe. Par exemple, un nom de classe peut être référencé de trois manières?: 1 Nom non qualifié, ou nom de classe sans préfixe , par exemple $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. 2. Nom qualifié, ou nom incluant le préfixe , tel que $a = new subnamespacefoo();. 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. 3.? 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. Ce qui suit est un exemple d'utilisation de ces trois méthodes?: Exemple Exemple Notez que pour accéder à n'importe quelle classe globale, fonction ou constante, vous pouvez utiliser un nom complet, tel que strlen() ou Exception ou INI_ALL. Accédez aux classes, fonctions et constantes globales à l'intérieur de l'espace de noms?: Espace de noms et fonctionnalités de langage dynamique Implémentation de l'espace de noms PHP Affecté par les caractéristiques dynamiques de sa 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. Instance Résultat de l'exécution du programme?: nom de classe ::__construct
nom de la fonction
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. Instance Accès dynamique aux éléments de l'espace de noms Résultat de l'exécution du programme?: classname::__construct
nom de fonction
mondial
nom de classe ::__construct
nom de la fonction
mondial
espace de nomsnomclasse::__construct
espace de nomsnomclasse::__construct
espace de nomsnomfonctionnom
espace de nomsnomfonctionnom
espace de noms
namespaced mot-clé d'espace de noms et constante __NAMESPACE__ Prise en charge de PHP deux méthodes abstraites pour accéder aux éléments dans l'espace de noms actuel, la constante magique __NAMESPACE__ et le 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. Exemple __NAMESPACE__ Exemple, dans Le code dans l'espace de noms résultat de l'exécution du programme?: "MonProjet" Instance __NAMESPACE__ exemple, code global Résultat de l'exécution du programme?: "" Instance La constante __NAMESPACE__ est utile lors de la création dynamique de noms, par exemple?: Créez des noms dynamiquement en utilisant __NAMESPACE__ Le mot-clé namespace 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. Instance opérateur d'espace de noms, code dans l'espace de noms Instance opérateur d'espace de noms, code global Utiliser l'espace de noms?: alias/import La prise en charge de l'espace de noms PHP a deux manières d'utiliser les alias ou les importations?: utiliser des alias pour les noms de classe ou utiliser des alias pour les noms d'espace de noms. Notez que PHP ne prend pas en charge l'importation de fonctions ou de constantes. 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 2. Une ligne contient plusieurs instructions d'utilisation 3. Importation et noms dynamiques 4. Importation et noms complets Utiliser l'espace de noms?: fonctions/constantes globales de secours Lorsque PHP rencontre une classe, une fonction ou un nom de constante non qualifié dans un espace de noms, 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 inclus dans l'espace de noms, vous devez utiliser le nom complet Par exemple?: 1. Accédez aux classes globales dans l'espace de noms Pour les fonctions et 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. Sauvegarder les fonctions/constantes globales dans l'espace de noms Espace global 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. 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. Instance Utiliser les instructions d'espace global Ordre des espaces de noms Depuis la création de l'espace 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. 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 lors de la compilation. temps. 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. Dans l'espace de noms, tous les noms qualifiés qui ne sont pas convertis selon les règles d'importation auront le nom actuel de l'espace de noms devant eux. 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 : 1. Recherchez une fonction nommée ABfoo() dans l'espace de noms actuel 2 Essayez de trouver et d'appeler la fonction globale foo. () dans l'espace. 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() : 1 Recherchez la classe ABC dans l'espace de noms actuel. 2. Essayez de charger automatiquement la classe ABC. Nouvelle analyse DE()?: 3. Ajoutez le nom de l'espace de noms actuel devant le nom de la classe pour devenir : ABDE, puis recherchez la classe. 4. 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é. <?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>
<?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的靜態(tài)方法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
?>
<?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
?>
<?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
?>
<?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
?>
<?php
namespace MyProject;
header("Content-type:text/html;charset=utf-8"); //設置編碼
echo '"', __NAMESPACE__, '"'; // 輸出 "MyProject"
?>
<?php
header("Content-type:text/html;charset=utf-8"); //設置編碼
echo '"', __NAMESPACE__, '"'; // 輸出 "MyProject"
?>
<?php
namespace MyProject;
function get($classname)
{
$a = __NAMESPACE__ . '\' . $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
?>
<?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
?>
<?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 對象
?>
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 實例化 My\Full\Classname 對象
NSname\subns\func(); // 調用函數 My\Full\NSname\subns\func
?>
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 實例化一個 My\Full\Classname 對象
$a = 'Another';
$obj = new $a; // 實際化一個 Another 對象
?>
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // instantiates object of class My\Full\Classname
$obj = new \Another; // instantiates object of class Another
$obj = new Another\thing; // instantiates object of class My\Full\Classname\thing
$obj = new \Another\thing; // instantiates object of class Another\thing
?>
<?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 類
?>
<?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";
}
?>
<?php
namespace A\B\C;
/* 這個函數是 A\B\C\fopen */
function fopen() {
/* ... */
$f = \fopen(...); // 調用全局的fopen函數
return $f;
}
?>
<?php
namespace A;
use B\D, C\E as F;
// 函數調用
foo(); // 首先嘗試調用定義在命名空間"A"中的函數foo()
// 再嘗試調用全局函數 "foo"
\foo(); // 調用全局空間函數 "foo"
my\foo(); // 調用定義在命名空間"A\my"中函數 "foo"
F(); // 首先嘗試調用定義在命名空間"A"中的函數 "F"
// 再嘗試調用全局函數 "F"
// 類引用
new B(); // 創(chuàng)建命名空間 "A" 中定義的類 "B" 的一個對象
// 如果未找到,則嘗試自動裝載類 "A\B"
new D(); // 使用導入規(guī)則,創(chuàng)建命名空間 "B" 中定義的類 "D" 的一個對象
// 如果未找到,則嘗試自動裝載類 "B\D"
new F(); // 使用導入規(guī)則,創(chuàng)建命名空間 "C" 中定義的類 "E" 的一個對象
// 如果未找到,則嘗試自動裝載類 "C\E"
new \B(); // 創(chuàng)建定義在全局空間中的類 "B" 的一個對象
// 如果未發(fā)現(xiàn),則嘗試自動裝載類 "B"
new \D(); // 創(chuàng)建定義在全局空間中的類 "D" 的一個對象
// 如果未發(fā)現(xiàn),則嘗試自動裝載類 "D"
new \F(); // 創(chuàng)建定義在全局空間中的類 "F" 的一個對象
// 如果未發(fā)現(xiàn),則嘗試自動裝載類 "F"
// 調用另一個命名空間中的靜態(tài)方法或命名空間函數
B\foo(); // 調用命名空間 "A\B" 中函數 "foo"
B::foo(); // 調用命名空間 "A" 中定義的類 "B" 的 "foo" 方法
// 如果未找到類 "A\B" ,則嘗試自動裝載類 "A\B"
D::foo(); // 使用導入規(guī)則,調用命名空間 "B" 中定義的類 "D" 的 "foo" 方法
// 如果類 "B\D" 未找到,則嘗試自動裝載類 "B\D"
\B\foo(); // 調用命名空間 "B" 中的函數 "foo"
\B::foo(); // 調用全局空間中的類 "B" 的 "foo" 方法
// 如果類 "B" 未找到,則嘗試自動裝載類 "B"
// 當前命名空間中的靜態(tài)方法或函數
A\B::foo(); // 調用命名空間 "A\A" 中定義的類 "B" 的 "foo" 方法
// 如果類 "A\A\B" 未找到,則嘗試自動裝載類 "A\A\B"
\A\B::foo(); // 調用命名空間 "A\B" 中定義的類 "B" 的 "foo" 方法
// 如果類 "A\B" 未找到,則嘗試自動裝載類 "A\B"
?>