Php 简明教程

PHP - Namespaces

我们经常将文件组织在不同的文件夹中。通常情况下,一个文件夹包含与某个目标、应用程序或类别相关联的文件。一个文件夹不能包含两个具有相同名称的文件,尽管不同的文件夹可能具有一个名称相同的文件,因此每个文件路径都是不同的。

We often organize the files in different folders. Usually a folder contains files related to a certain objective, or application or category. A folder can’t contain two files with the same name, though different folders may have a file of the same name so that the path of each file is different.

PHP 中的命名空间理念有点类似。在 PHP 中,命名空间允许在不同上下文中使用相同名称的类或函数或常量,而不会出现任何冲突,从而封装这些项。

The idea of namespaces in PHP is somewhat similar. In PHP, namespaces allow classes or functions or constants of same name be used in different contexts without any conflict, thereby encapsulating these items.

PHP 命名空间是根据它们的关联性对类/函数等进行的逻辑分组。正如同名的文件可以存在于两个不同的文件夹中一样,命名空间中也可以定义一个特定名称的类。此外,由于我们指定文件的完整路径来获取访问权限,因此我们需要指定类及其命名空间的完整名称。

A PHP namespace is logical grouping of classes/functions etc., depending on their relevance. Just as a file with same name can exist in two different folders, a class of a certain name can be defined in two namespaces. Further, as we specify the complete path of a file to gain access, we need to specify full name of class along with namespace.

随着应用程序规模的不断增大,包括许多类和函数定义,为每个类/函数提供一个唯一的名称可能会变得繁琐并且不够优雅。使用命名空间可让您以一种简洁的方式组织此类代码块。例如,如果我们需要声明一个 calculate() 函数来计算面积和税费,我们可以创建两个命名空间 area 和 tax,并在其中使用 calculate() 而不必将它们定义为类似 calculate_area() 和 calculate_tax() 的内容。

As your application size becomes bigger, involving many class and function definitions, giving give a unique name to each class/function may become tedious and not exactly elegant. Using namespaces lets you organize such code blocks in a neat manner. For example, if we need to declare a calculate() function to calculate area as well as tax, instead of defining them as something like calculate_area() and calculate_tax(), we can create two namespaces area and tax and use calculate() inside them.

Advantages of Namespace

下面列出了一些使用 PHP 中的命名空间的优点 −

Here are some of the advantages of using namespaces in PHP −

  1. Namsepaces help in avoiding name collisions between classes/functions/constants defined by someone with third-party classes/functions/constants.

  2. Namespaces provide the ability to alias (or shorten) Extra_Long_Names, thereby improving the readability of source code.

  3. PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants. Namespace names are case – insensitive.

Defining a Namespace

PHP 的名称空间关键字用于定义新的命名空间。

PHP’s namespace keyword is used to define a new namespace.

namespace myspace;

包含命名空间的 “.php” 文件必须在文件顶部声明命名空间,然后再声明任何其他内容(声明指令除外)。在命名空间中声明类、函数和常量会影响其访问权限。

A ".php" file containing a namespace must declare the namespace at the top of the file before any other (except the declare directive). Declaration of class, function and constants inside a namespace affects its access.

一个 PHP 脚本可以除了定义命名空间之外,还包含其他代码。为了加载在相同代码中定义的命名空间,PHP 具有“use”关键字。

A PHP script may contain other code apart from the definition of a namespace. To load the namespace defined in the same code, PHP has the "use" keyword.

use myspace;

Example

在以下 “hello.php” 脚本中,我们在 myspace 命名空间中定义了一个 hello() 函数,并在当前脚本中加载该命名空间之后对其进行调用。

In the following "hello.php" script, we define a hello() function inside myspace namespace, and call it after loading the namespace in the current script.

<?php
   namespace myspace;
   function hello() {
      echo "Hello World";
   }
   use myspace;
   myspace\hello();
?>

它将生成以下 output

It will produce the following output

Hello World

请注意,您必须用名称空间完整的名称限定 hello() 函数,其中包括名称空间 - myspace\hello()。

Note that you must qualify the hello() function with its full name that includes the namespace - myspace\hello().

Include Namespace

可以有一个脚本包含名称空间声明,以及在其中使用 include 语句加载该名称空间的另一个脚本。

You may have one script consisting of a declaration of a namespace, and the other script in which the namespace is loaded with include statement.

a.php

<?php
   namespace myspace {
      function hello() {
         echo "Hello World in myspace";
      }
   }
?>

b.php

<?php
   include 'a.php';
   myspace\hello();
?>

它将生成以下 output

It will produce the following output

Hello World in myspace

在当前的脚本(如上所述的“b.php”)中,可能还有一个函数与 include 文件中函数名称相同。附加名称空间的完全限定函数,帮助解析器解决名称冲突。

There may be a case where the current script ("b.php" as above) also has a function of the same name as in the included file. The fully qualified function that prepends the namespace, helps the parser to resolve the name conflict.

Example

请看以下示例:

Take a look at the following example −

<?php
   include 'a.php';
   function hello() {
      echo "Hello World from current namespace";
   }
   hello();
   myspace\hello();
?>

它将生成以下 output

It will produce the following output

Hello World from current namespace
Hello World in myspace

Example

如上所述,名称空间声明必须在最上面,紧跟在 <?php 标签的后面。否则,解析器会抛出致命错误。

As mentioned above, the namespace declaration must be at the top, immediately after the opening <?php tag. Otherwise the parser throws a fatal error.

<?php
   echo "hello"
   namespace myspace;
   function hello() {
      echo "Hello World";
   }
   use myspace;
   myspace\hello();
?>

它将生成以下 output

It will produce the following output

PHP Parse error:  syntax error, unexpected token "namespace",
expecting "," or ";" in /home/cg/root/67771/main.php on line 4

上面的错误信息明确指出,在名称空间声明之前,只允许出现“declare 语句”。

The above error message makes it clear that only the "declare statement" is allowed to appear before the namespace declaration.

<?php
   declare (strict_types=1);
   namespace myspace;
   function hello() {
      echo "Hello World";
   }
   use myspace;
   myspace\hello();
?>

Relative Namespace

可以通过相对于名称空间的路径引用当前名称空间中的对象,如函数、类和常量。

The objects such as functions, classes and constants may be accessed in the current namespace by referring the with relative namespace paths.

在下面的示例中,“b.php”包含一个带有 hello() 函数和 TEMP 常量的名称空间 space1\myspace。这些对象也在“a.php”中定义的名称空间 space1 中被定义。

In the following example, "b.php" contains a namespace space1\myspace with a hello() function and a TEMP constant. The same objects are also defined in namespace space1, present in "a.php".

显然,当“b.php”被包含在“a.php”时,“myspace”是“space1”的子空间。因此,通过对其相对名称空间(也是 TEMP 常量)加上前缀来调用来自“myspace”的 hello()。

Obviously, when "b.php" is included in "a.php", "myspace" is a subspace of "space1". Hence, hello() from "myspace" is called by prefixing its relative namespace (also the TEMP constant)

b.php

<?php
   namespace space1\myspace;
   const TEMP = 10;
   function hello() {
      echo "Hello from current namespace:" . __NAMESPACE__ . ;
   }
?>

a.php

<?php
   namespace space1;
   include 'b.php';
   function hello() {
      echo "Hello from current namespace:" . __NAMESPACE__ . ;
   }
   const TEMP = 100;
   hello();            // current namespace
   myspace\hello();   // sub namespace

   echo "TEMP : " . TEMP . " in " . __NAMESPACE__ . ;
   echo "TEMP : " . myspace\TEMP  . " \\in space1\\myspace\n";
?>

它将生成以下 output

It will produce the following output

Hello from current namespace:space1
Hello from current namespace:space1\myspace
TEMP : 100 in space1
TEMP : 10 in space1\myspace

Absolute Namespace

也可以通过附加绝对名称空间路径来访问任何名称空间中的函数/常量。例如,“b.php”中的 hello() 是“\space\myspace\hello()”。

You can also access the functions/constants from any namespace by prefixing the absolute namespace path. For example, hello() in "b.php" is "\space\myspace\hello()".

a.php

<?php
   namespace space1;
   include 'b.php';
   function hello() {
      echo "Hello from current namespace:" . __NAMESPACE__ . ;
   }
   const TEMP = 100;
   \space1\hello();	             //current namespace
   \space1\myspace\hello();	    //sub namespace

   echo "TEMP: " . \space1\TEMP . " in " . __NAMESPACE__ . ;
   echo "TEMP: " . \space1\myspace\TEMP  . " in space1\\myspace\n";
?>

NAMESPACE 是 PHP 中的预定义常量,用于返回当前名称空间的名称。

The NAMESPACE is a predefined constant in PHP that returns the name of current namespace.

Namespace Rules

通过遵循以下规则,可以解决不同名称空间之间出现的函数/类/常量名称冲突:

Any conflict in the names of function/classes/constants appearing between different namespaces is resolved by following these rules −

  1. A namespace identifier without namespace separator symbol (/) means it is referring to current namespace. This is an unqualified name.

  2. If it contains separator symbol as in myspace\space1, it resolves to a subnamespace space1 under myspace. Such type of naming is relative namespace.

  3. Name of fully qualified namespace starts with the "\" character. For example, "\myspace" or "\myspace\space1".

  4. Fully qualified names resolve to absolute namespace. For example \myspace\space1 resolves to myspace\space1 namespace

  5. If the name occurs in the global namespace, the "namespace\" prefix is removed. For example, "namespace\space1" resolves to space1.

  6. However, if it occurs inside another namespace, it is treated differently. For example, if namespace\space1 is inside myspace, it is equivalent to "myspace\space1".

  7. First segment of the name in qualified name is translated according to the current class/namespace import table.

  8. If no import rule applies, the current namespace is prepended to the name.

  9. class-like names are translated according to the class/namespace import table, function names according to the function import table and constants according to the constant import table.

  10. For unqualified names, if no import rule applies and the name refers to a function or constant and the code is outside the global namespace, the name is resolved at runtime. First it looks for a function from the current namespace, then it tries to find and call the global function.