使用命名空间:基础

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

在讨论命名空间的使用之前,了解 PHP 如何知道您的代码请求哪个命名空间元素非常重要。PHP 命名空间与文件系统的简单类比可以帮助理解。在文件系统中,有三种方法可以访问文件

  1. 相对文件名,例如 foo.txt。这解析为 currentdirectory/foo.txt,其中 currentdirectory 是当前占用的目录。因此,如果当前目录是 /home/foo,则名称解析为 /home/foo/foo.txt
  2. 相对路径名,例如 subdirectory/foo.txt。这解析为 currentdirectory/subdirectory/foo.txt
  3. 绝对路径名,例如 /main/foo.txt。这解析为 /main/foo.txt
同样的原理可以应用于 PHP 中的命名空间元素。例如,类名可以通过三种方式引用
  1. 非限定名称或无前缀类名,例如 $a = new foo();foo::staticmethod();。如果当前命名空间是 currentnamespace,则解析为 currentnamespace\foo。如果代码是全局的、非命名空间代码,则解析为 foo 有一点需要注意:函数和常量的非限定名称将解析为全局函数和常量,如果未定义命名空间函数或常量。有关详细信息,请参见 使用命名空间:回退到全局函数/常量
  2. 限定名称或带前缀类名,例如 $a = new subnamespace\foo();subnamespace\foo::staticmethod();。如果当前命名空间是 currentnamespace,则解析为 currentnamespace\subnamespace\foo。如果代码是全局的、非命名空间代码,则解析为 subnamespace\foo
  3. 完全限定名称或带全局前缀运算符的前缀名称,例如 $a = new \currentnamespace\foo();\currentnamespace\foo::staticmethod();。这始终解析为代码中指定的文字名称,currentnamespace\foo

以下是在实际代码中三种语法类型的示例

file1.php

<?php
namespace Foo\Bar\subnamespace;

const
FOO = 1;
function
foo() {}
class
foo
{
static function
staticmethod() {}
}
?>

file2.php

<?php
namespace Foo\Bar;
include
'file1.php';

const
FOO = 2;
function
foo() {}
class
foo
{
static function
staticmethod() {}
}

/* 非限定名称 */
foo(); // 解析为函数 Foo\Bar\foo
foo::staticmethod(); // 解析为类 Foo\Bar\foo,方法 staticmethod
echo FOO; // 解析为常量 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
?>

请注意,要访问任何全局类、函数或常量,可以使用完全限定名称,例如 \strlen()\Exception 或 \INI_ALL

示例 #1 从命名空间内部访问全局类、函数和常量

<?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
?>

添加注释

用户贡献的注释 5 个注释

richard at richard-sumilang dot com
16 年前
在命名空间中扩展类的语法保持不变。

让我们将此称为 Object.php

<?php

namespace com\rsumilang\common;

class
Object{
// ... 代码 ...
}

?>

现在让我们创建一个名为 String 的类,它在 String.php 中扩展了对象

<?php

class String extends com\rsumilang\common\Object{
// ... 代码 ...
}

?>

现在,如果您在与 Object 相同的命名空间中定义了类 String,那么您不必指定完整的命名空间路径

<?php

namespace com\rsumilang\common;

class
String extends Object
{
// ... 代码 ...
}

?>

最后,您还可以将命名空间名称别名为使用更短的名称来扩展您的类,以防您的类在单独的命名空间中

<?php

namespace com\rsumilang\util;
use
com\rsumlang\common as Common;

class
String extends Common\Object
{
// ... 代码 ...
}

?>

- Richard Sumilang
匿名
9 年前
<?php

namespace Foo;

try {
// 这里发生了糟糕的事情
// 这将从 SPL 抛出一个新的异常
}
catch (
Exception as $ex) {
// 我们永远不会到达这里
// 这是因为我们正在捕获 Foo\Exception
}
?>

相反,使用完全限定名称来捕获异常

<?php

namespace Foo;

try {
// 这里有一些糟糕的东西
// 这将抛出来自 SPL 的新异常
}
catch (
\Exception as $ex) {
// 现在我们终于可以到达这里了
}
?>
Lukas Z
12 年前
因为变量永远不会受命名空间影响,而是始终是全局的,所以命名空间内的变量不会覆盖其他变量。
"虽然任何有效的 PHP 代码都可以包含在命名空间内,但只有四种类型的代码会受到命名空间的影响:类、接口、函数和常量。"

来源:"定义命名空间"
https://php.net/manual/en/language.namespaces.definition.php
tom at tomwardrop dot com
12 年前
似乎文件系统类比只进行到了一定程度。缺少一项非常有用的功能,即相对向上导航命名空间链,例如:

<?php
namespace MyProject {
class
Person {}
}

namespace
MyProject\People {
class
Adult extends ..\Person {}
}
?>

这将非常有用,特别是当您拥有非常深的命名空间时。它将避免您必须键入完整的命名空间来引用上一级的资源。
philip dot preisser at arcor dot de
13 年前
使用变量可以覆盖其他命名空间中相等的变量

<?php // php5 - package-version : 5.3.5-1ubuntu7.2

namespace
main
{}

namespace
main\sub1
{
$data = 1;
}

namespace
main\sub2
{
echo
$data;// 1
$data = 2;
}

namespace
main\sub1
{
echo
$data;// 2
$data = 1;
}

namespace
{
echo
$data;// 1
}

?>
To Top