2024年PHP日本大会

使用命名空间:基础

(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中扩展了object

<?php

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

?>

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

<?php

命名空间 com\rsumilang\common;

String 扩展 Object
{
// ... 代码 ...
}

?>

最后,您也可以为命名空间名设置别名,以便为正在扩展的类使用较短的名称,以防您的类位于单独的命名空间中。

<?php

命名空间 com\rsumilang\util;
use
com\rsumlang\common as Common;

String 扩展 Common\Object
{
// ... 代码 ...
}

?>

- Richard Sumilang
匿名用户
10 年前
<?php

命名空间 Foo;

尝试 {
// 此处存在严重问题
// 将抛出来自 SPL 的新异常
}
捕获 (
Exception as $ex) {
// 我们永远不会到达这里
// 这是因为我们正在捕获 Foo\Exception
}
?>

改用异常的全限定名来捕获它。

<?php

命名空间 Foo;

尝试 {
// 此处存在严重问题
// 将抛出来自 SPL 的新异常
}
捕获 (
\Exception as $ex) {
// 现在我们终于可以到达这里了
}
?>
Lukas Z
12 年前
命名空间内的变量不会覆盖其他变量,因为变量不受命名空间影响,始终是全局的。
“尽管任何有效的 PHP 代码都可以包含在命名空间中,但只有四种类型的代码受命名空间的影响:类、接口、函数和常量。”

来源:“定义命名空间”
https://php.net/manual/en/language.namespaces.definition.php
tom at tomwardrop dot com
12 年前
文件系统类比似乎只到此为止。缺少的一个非常有用的功能是向上遍历命名空间链的相对导航,例如:

<?php
命名空间 MyProject {
Person {}
}

命名空间
MyProject\People {
Adult 扩展 ..\Person {}
}
?>

这将非常有用,尤其是在命名空间非常深的情况下。它可以避免您为了引用上一级资源而不得不键入完整的命名空间。
philip dot preisser at arcor dot de
13 年前
使用变量可以覆盖其他命名空间中相等的变量。

<?php // php5 - 包版本:5.3.5-1ubuntu7.2

命名空间
main
{}

命名空间
main\sub1
{
$data = 1;
}

命名空间
main\sub2
{
echo
$data;// 1
$data = 2;
}

命名空间
main\sub1
{
echo
$data;// 2
$data = 1;
}

命名空间
{
echo
$data;// 1
}

?>
To Top