Maison  >  Article  >  développement back-end  >  Qu'est-ce qu'un espace de noms ? Explication détaillée des espaces de noms en PHP

Qu'est-ce qu'un espace de noms ? Explication détaillée des espaces de noms en PHP

怪我咯
怪我咯avant
2017-06-14 11:49:585944parcourir

Qu'est-ce qu'un espace de noms ? Cet article vous donnera une compréhension approfondie des espaces de noms en PHP. J'espère qu'il vous sera utile.

Qu'est-ce qu'un espace de noms ? Explication détaillée des espaces de noms en PHP

Qu'est-ce qu'un espace de noms ?

Au sens large, l'espace de noms est une façon d'encapsuler les choses, et ce concept abstrait peut être vu à de nombreux endroits. Par exemple, les répertoires sont utilisés dans les systèmes d'exploitation pour regrouper les fichiers associés et servent d'espaces de noms pour les fichiers du répertoire.

À titre d'exemple simple, 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, par exemple /home/greg/foo.txt. L'application de ce principe au domaine de la programmation est le concept d'espace de noms.

Définition de l'espace de noms

L'espace de noms en PHP a été ajouté en PHP5.3, si vous connaissez le C++, alors les espaces de noms ne sont pas nouveaux. Cependant, les espaces de noms restent très importants 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 conflits de noms entre

  • 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.

1) Définir l'espace de noms (en utilisant le mot-clé namespace)

Bien que tout code PHP légal puisse être inclus dans l'espace de noms, seuls les types de le code tel que les classes (y compris les classes et traits abstraits), les interfaces, les fonctions et les constantes sont affectés par l'espace de noms.

La définition d'un espace de noms doit être déclarée via le mot-clé namespace. Le format de syntaxe est le suivant :

namespace 命名空间名;

[Exemple] Montrons comment définir un espace de noms :

<?php
    namespace MyProject;    // 定义名为 MyProject 的命名空间。
    const CONNECT_OK = 1;
    class Myclass {
        /* ... */
    }
    function Myfunc() {
        /* ... */
    }
?>

Avant de déclarer l'espace de noms, à l'exception de l'instruction declare utilisée pour définir la méthode d'encodage du fichier source, tout le code non PHP (y compris les caractères d'espacement) ne peut pas apparaître avant la déclaration de l'espace de noms.

De plus, contrairement aux autres fonctionnalités du langage PHP, le même espace de noms peut être défini dans plusieurs fichiers, ce qui permet de diviser et de stocker le contenu du même espace de noms dans différents fichiers.

2) Définir des sous-espaces de noms

est très similaire aux répertoires et aux fichiers. Les espaces de noms en PHP permettent également de spécifier des noms d'espaces de noms hiérarchiques. Ainsi, le nom de l'espace de noms peut être défini de manière hiérarchique :

namespace App\Model;
namespace App\Controller\Home;

[Exemple] Définir un sous-espace de noms :

<?php
    namespace MyProject\Controller\Home;    // 定义名为 MyProject 的命名空间。
    const CONNECT_OK = 1;
    class Myclass {
        /* ... */
    }
    function Myfunc() {
        /* ... */
    }
?>

3) Dans le même file Définir plusieurs espaces de noms dans

Vous pouvez également définir plusieurs espaces de noms dans un seul fichier. Il existe deux formes de syntaxe pour définir plusieurs espaces de noms dans le même fichier. Voici un exemple à illustrer :

[Exemple] Définissez plusieurs espaces de noms - syntaxe de combinaison simple.

<?php
    namespace MyProject;
    const CONNECT_OK = 1;
    class className {
        /* ... */
    }
    namespace AnotherProject;
    const CONNECT_OK = 1;
    class className {
        /* ... */
    }
?>

[Exemple] Définissez plusieurs espaces de noms - syntaxe d'accolade { }.

<?php
    namespace MyProject{
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
    namespace AnotherProject{
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
?>

Dans la pratique réelle de la programmation, il n'est pas recommandé de définir plusieurs espaces de noms dans le même fichier. La définition de plusieurs espaces de noms est principalement utilisée pour combiner plusieurs scripts PHP dans le même fichier. Il est recommandé d’utiliser la syntaxe des accolades lors de la définition de plusieurs espaces de noms.

Pour combiner le code dans le non-espace de noms global avec le code dans l'espace de noms, vous ne pouvez utiliser que la syntaxe sous forme d'accolades. En même temps, le code global doit utiliser une instruction d'espace de noms sans nom plus. accolades, comme suit :

<?php
    namespace MyProject{        // 命名空间中的代码
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
    namespace {                 // 命名空间外的全局代码
        $obj = new MyProject\className();
    }
?>

Utilisation des espaces de noms : principes de base

Avant de discuter de la façon d'utiliser les espaces de noms, vous devez comprendre PHP Comment pour savoir quel élément d'espace de noms utiliser. Nous pouvons faire une analogie simple 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 :

  • 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. Par conséquent, si le répertoire actuel est /home/foo, le nom du fichier est analysé comme /home/foo/foo.txt

  • Le format du nom de chemin relatif est tel que sous-répertoire/foo ; .SMS. Il sera analysé comme currentdirectory/subdirectory/foo.txt ;

  • Le format du nom de chemin absolu est tel que /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 sous un espace de noms peut être référencé de trois manières :

  • un nom non qualifié ou un nom de classe qui n'inclut pas de préfixe, tel que $a=new foo(); ou foo::staticmethod();. Si l'espace de noms actuel est currentnamespace, alors foo sera résolu en currentnamespacefoo. Si le code utilisant foo est global et n'est contenu dans aucun espace de noms, alors foo sera résolu en foo.

  • 限定名称,或包含前缀的名称,例如$a = new subnamespace\foo();subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为 subnamespace\foo。

  • 完全限定名称,或包含了全局前缀操作符的名称,例如$a = new \currentnamespace\foo();\currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名 currentnamespace\foo。

警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。

下面是一个使用这三种方式的实例,我们需要两个 PHP 源文件,分别是 demo.php 和 index.php,示例代码如下:

1) demo.php

<?php
    namespace Foo\Bar\Demo;
    const FOO = 1;
    function foo() {}
    class foo
    {
        public function demo() {
            echo &#39;命名空间为:Foo\Bar\Demo&#39;;
        }
    }
?>

2) index.php

<?php
    namespace Foo\Bar;
    include &#39;Demo.php&#39;;
    const FOO = 2;
    function foo() {
        echo &#39;Foo\Bar 命名空间下的 foo 函数<br>&#39;;
    }
    class foo
    {
        static function demo(){
            echo &#39;命名空间为:Foo\Bar<br>&#39;;
        }
    }
    /* 非限定名称 */
    foo();                  // 解析为 Foo\Bar\foo resolves to function Foo\Bar\foo
    foo::demo();            // 解析为类 Foo\Bar\foo 的静态方法 staticmethod。
    echo FOO.&#39;<br>&#39;;        // 解析为常量 Foo\Bar\FOO
    /* 限定名称 */
    Demo\foo();             // 解析为函数 Foo\Bar\Demo\foo
    Demo\foo::demo();       // 解析为类 Foo\Bar\Demo\foo,
                            // 以及类的方法 demo
    echo Demo\FOO.&#39;<br>&#39;;   // 解析为常量 Foo\Bar\Demo\FOO
                                     
    /* 完全限定名称 */
    \Foo\Bar\foo();         // 解析为函数 Foo\Bar\foo
    \Foo\Bar\foo::demo();   // 解析为类 Foo\Bar\foo, 以及类的方法 demo
    echo \Foo\Bar\FOO.&#39;<br>&#39;; // 解析为常量 Foo\Bar\FOO
?>

运行结果如下:

Foo\Bar 命名空间下的 foo 函数
命名空间为:Foo\Bar
2
Foo\Bar\Demo 命名空间下的 foo 函数
命名空间为:Foo\Bar\Demo
1
Foo\Bar 命名空间下的 foo 函数
命名空间为:Foo\Bar
2

注意:访问任意全局类、函数或常量,都可以使用完全限定名称,例如 \strlen() 或 \Exception 等。

使用命名空间:别名/导入

PHP 允许通过别名引用或导入的方式来使用外部的命名空间,这是命名空间的一个重要特征。这有点类似于在类 unix 文件系统中可以创建对其它的文件或目录的符号连接。

使用 use 关键字可以实现命名空间的导入,从 PHP5.6 开始允许导入函数和常量,并为它们设置别名。语法格式如下:

use namespace;

在 PHP 中,别名是通过操作符 use 与 as 来实现的,语法格式如下:

use 命名空间 as 别名;

【示例】使用 use 操作符导入和使用别名。

<?php
    namespace foo;
    use My\Full\Classname as Another;
    // 下面的例子与 use My\Full\NSname as NSname 相同
    use My\Full\NSname;
    // 导入一个全局类
    use ArrayObject;
    // 导入一个函数
    use function My\Full\functionName;
    // 导入一个函数并定义别名
    use function My\Full\functionName as func;
    // 导入一个常量
    use const My\Full\CONSTANT;
    $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 对象
    func();                         // 调用 My\Full\functionName 函数
    echo CONSTANT;                  // 打印 My\Full\CONSTANT 常量
?>

注意:对命名空间中的名称(包含命名空间分隔符的完全限定名称,如 Foo\Bar ,以及相对的不包含命名空间分隔符的全局名称,如 FooBar)来说,前导的反斜杠是不必要的也是不推荐的,因为导入的名称必须是完全限定的,不会根据当前的命名空间作相对解析。

为了简化操作,PHP 还支持在一行中导入多个命名空间,中间使用,隔开,示例代码如下:

<?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 = &#39;Another&#39;;
    $obj = new $a;      // 实际化一个 Another 对象
?>

另外,导入操作只影响非限定名称和限定名称。完全限定名称由于是确定的,故不受导入的影响。

namespace 关键字和 __NAMESPACE__ 常量

PHP 支持两种抽象的访问当前命名空间内部元素的方法,__NAMESPACE__ 魔术常量和 namespace 关键字。

__NAMESPACE__ 常量的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它是一个空的字符串。示例代码如下:

<?php
    namespace App\Controller\Home;
    echo __NAMESPACE__;
?>

运行结果如下:

App\Controller\Home

namespace 关键字可用来显式访问当前命名空间或子命名空间中的元素,它等价于类中的 self 操作符。示例代码如下:

<?php
    namespace MyProject;
    use Foo\Bar\Demo as demo;       // 导入 Foo\Bar\Demo 命名空间
    blah\mine();                    // 调用 MyProject\blah\mine() 函数
    namespace\blah\mine();          // 调用 MyProject\blah\mine() 函数
    namespace\func();               // 调用 MyProject\func() 函数
    namespace\sub\func();           // 调用 MyProject\sub\func() 函数
    namespace\cname::method();      // 调用 MyProject\cname 类的静态方法 method
    $a = new namespace\sub\cname(); // 实例化 MyProject\sub\cname 对象
    $b = namespace\CONSTANT;        // 将常量 MyProject\CONSTANT 的值赋给 $b
?>

命名空间名称解析规则

在说明名称解析规则之前,我们先来看看命名空间名称的定义:

  • 非限定名称:名称中不包含命名空间分隔符的标识符,例如 Foo;

  • 限定名称:名称中含有命名空间分隔符的标识符,例如 Foo\Bar;

  • 完全限定名称:名称中包含命名空间分隔符,并以命名空间分隔符开始的标识符,例如 \Foo\Bar。namespace\Foo 也是一个完全限定名称。

名称解析遵循下列规则:

  • Les appels aux noms complets de fonctions, classes et constantes sont résolus au moment de la compilation. Par exemple, le nouveau AB se résout 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 selon les règles d'importation actuelles. Par exemple, si l'espace de noms ABC est importé en C, alors les appels à CDe() seront convertis en ABCDe();
  • Dans l'espace de noms, tous les noms qualifiés qui ne sont pas convertis selon les règles d'importation seront Prepend avec le nom actuel de l'espace de noms. 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) du nom d'importation court). Par exemple, si l'espace de noms ABC est importé en tant que C, alors new C() est converti en new ABC();
  • À l'intérieur d'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 de. Par exemple, un appel à la fonction foo() est analysé comme ceci :
    • Recherchez une fonction nommée ABfoo() dans l'espace de noms actuel

    • Essayez ; trouver Et 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) à l'intérieur d'un espace de noms (par exemple AB) sont résolus au moment de l'exécution. Voici le processus d'analyse pour appeler new C() et new DE() :
    • Analyse de new C() :

      • Trouver la classe ABC dans le courant espace de noms ;
      • Essayez de charger automatiquement la classe ABC.
    • Analyse du nouveau DE() :

      • Ajoutez le nom de l'espace de noms actuel devant le nom de la classe pour devenir : ABDE, puis recherchez pour 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é.

Apprentissage recommandé : "Tutoriel vidéo PHP"

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer