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

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

使用别名或导入来引用外部完全限定名称的能力是命名空间的重要特性。这类似于基于 Unix 的文件系统创建指向文件或目录的符号链接的能力。

PHP 可以为常量、函数、类、接口、特质、枚举和命名空间创建别名(/导入)。

别名使用 use 运算符完成。以下示例展示了所有 5 种导入方式

示例 #1 使用 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 还支持一个方便的快捷方式,可以在同一行上放置多个 use 语句

示例 #2 使用 use 运算符进行导入/别名,多个 use 语句组合在一起

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 实例化类 My\Full\Classname 的对象
NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func
?>

导入是在编译时执行的,因此不会影响动态类、函数或常量名称。

示例 #3 导入和动态名称

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 实例化类 My\Full\Classname 的对象
$a = 'Another';
$obj = new $a; // 实例化类 Another 的对象
?>

此外,导入只影响非限定名称和限定名称。完全限定名称是绝对的,不受导入影响。

示例 #4 导入和完全限定名称

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 实例化类 My\Full\Classname 的对象
$obj = new \Another; // 实例化类 Another 的对象
$obj = new Another\thing; // 实例化类 My\Full\Classname\thing 的对象
$obj = new \Another\thing; // 实例化类 Another\thing 的对象
?>

导入的范围规则

use 关键字必须在文件的外部范围(全局范围)或命名空间声明内部声明。这是因为导入是在编译时完成的,而不是在运行时完成的,因此它不能是块范围的。以下示例将展示 use 关键字的非法用法

示例 #5 非法导入规则

<?php
namespace Languages;

function
toGreenlandic()
{
use
Languages\Danish;

// ...
}
?>

注意:

导入规则是按文件为基础的,这意味着包含的文件 *不会* 继承父文件的导入规则。

分组 use 声明

从同一个 namespace 导入的类、函数和常量可以在单个 use 语句中分组。

<?php

use some\namespace\ClassA;
use
some\namespace\ClassB;
use
some\namespace\ClassC as C;

use function
some\namespace\fn_a;
use function
some\namespace\fn_b;
use function
some\namespace\fn_c;

use const
some\namespace\ConstA;
use const
some\namespace\ConstB;
use const
some\namespace\ConstC;

// 等效于以下分组的 use 声明
use some\namespace\{ClassA, ClassB, ClassC as C};
use function
some\namespace\{fn_a, fn_b, fn_c};
use const
some\namespace\{ConstA, ConstB, ConstC};
添加注释

用户贡献的注释 21 条注释

192
dominic_mayers at yahoo dot com
7 年前
关键字“use”已被循环使用于三个不同的应用程序
1- 在命名空间中导入/别名类、特征、常量等,
2- 在类中插入特征,
3- 在闭包中继承变量。
此页面仅介绍第一个应用程序:导入/别名。特征可以插入类,但这与在命名空间中导入特征不同,在命名空间中导入特征不能在块作用域中完成,如示例 5 所示。这可能会令人困惑,尤其是在所有搜索关键字“use”都指向此处有关导入/别名的文档时。
155
anon
10 年前
<?php use ?> 语句不会加载类文件。您必须使用 <?php require ?> 语句或使用自动加载函数来完成此操作。
56
Mawia HL
6 年前
以下是如何使用单个“use”关键字导入类、函数和常量的一种便捷方法

<?php
use Mizo\Web\ {
Php\WebSite,
Php\KeyWord,
Php\UnicodePrint,
JS\JavaScript,
function
JS\printTotal,
function
JS\printList,
const
JS\BUAIKUM,
const
JS\MAUTAM
};
?>
80
k at webnfo dot com
11 年前
请注意,您不能为全局命名空间创建别名

use \ as test;

echo test\strlen('');

无法正常运行。
33
xzero at elite7hackers dot net
7 年前
我找不到这个问题的答案,所以我自己测试了一下。
我认为值得注意的是

<?php
use ExistingNamespace\NonExsistingClass;
use
ExistingNamespace\NonExsistingClass as whatever;
use
NonExistingNamespace\NonExsistingClass;
use
NonExistingNamespace\NonExsistingClass as whatever;
?>

除非您实际尝试使用您尝试导入的类,否则上述代码都不会实际导致错误。

<?php
// 这段代码将发出标准 PHP 错误,因为类不存在。
22
me at ruslanbes dot com
8 年前
请注意,代码“use ns1\c1”可能指的是从命名空间“ns1”中导入类“c1”,也可能指的是导入整个命名空间“ns1\c1”,甚至可能在一行代码中导入两者。例如

<?php
namespace ns1;

class
c1{}

namespace
ns1\c1;

class
c11{}

namespace
main;

use
ns1\c1;

$c1 = new c1();
$c11 = new c1\c11();

var_dump($c1); // object(ns1\c1)#1 (0) { }
var_dump($c11); // object(ns1\c1\c11)#2 (0) { }
28
c dot 1 at smithies dot org
13 年前
如果您在 CLI 上测试代码,请注意命名空间别名不起作用!

(在我继续之前,此示例中的所有反斜杠都被更改为百分号,因为否则我无法在发布预览中获得合理的显示结果。请在以后将所有百分号都视为反斜杠。)

假设您有一个您想在 myclass.php 中测试的类

<?php
namespace my%space;
class
myclass {
// ...
}
?>

然后您进入 CLI 进行测试。您可能会认为这会起作用,因为您逐行输入它

require 'myclass.php';
use my%space%myclass; // 应该将“myclass”设置为“my%space%myclass”的别名
$x = new myclass; // 致命错误

我认为这是因为别名仅在编译时解析,而 CLI 只是评估语句;因此,use 语句在 CLI 中无效。

如果您将测试代码放到 test.php 中
<?php
require 'myclass.php';
use
my%space%myclass;
$x = new myclass;
//...
?>
它将正常运行。

我希望这能减少过早秃头的人数。
20
x at d dot a dot r dot k dot REMOVEDOTSANDTHIS dot gray dot org
11 年前
只要每次调用都在不同的别名下导入,您就可以多次“use”同一资源。

例如

<?php
use Lend;
use
Lend\l1;
use
Lend\l1 as l3;
use
Lend\l2;
use
Lend\l1\Keller;
use
Lend\l1\Keller as Stellar;
use
Lend\l1\Keller as Zellar;
use
Lend\l2\Keller as Dellar;

...

?>

在上面的示例中,“Keller”、“Stellar”和“Zellar”都是对“\Lend\l1\Keller”的引用,就像“Lend\l1\Keller”、“l1\Keller”和“l3\Keller”一样。
16
cl
11 年前
有一点并非显而易见,尤其是在 PHP 5.3 中,即导入内的命名空间解析不会递归解析。即:如果您为一个导入创建别名,然后在另一个导入中使用该别名,那么这个后者的导入将不会与前者的导入完全解析。

例如
use \Controllers as C;
use C\First;
use C\Last;

First 和 Last 命名空间都不会像您预期的那样解析为 \Controllers\First 或 \Controllers\Last。
3
ultimater at gmail dot com
7 年前
请注意,“use”导入/别名仅适用于当前命名空间块。

<?php

namespace SuperCoolLibrary
{
class
Meta
{
static public function
getVersion()
{
return
'2.7.1';
}
}
}

namespace
{
use
SuperCoolLibrary\Meta;
echo
Meta::getVersion();// 输出 2.7.1
}

namespace
{
echo
Meta::getVersion();// 致命错误
}

?>

要获得预期行为,您需要使用
class_alias('SuperCoolLibrary\Meta','Meta');
1
ZhangLiang
7 年前
在中文中,翻译存在错误
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
应该是
// 如果不使用 "use ArrayObject" ,则实例化一个 foo\ArrayObject 对象

/*********************************************/
中文下翻译有错误
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
这句话应该是
// 如果不使用 "use ArrayObject" ,则实例化一个 foo\ArrayObject 对象
0
eithed at google mail
3 年前
请记住,为命名空间创建别名完全没问题,例如

<?php
use A\B\C\D\E\User;

new
User();
?>

也可以写成

<?php
use A\B\C\D\E as ENamespace;

new
ENamespace\User();
?>

但是以下操作将无法正常运行

<?php
use A\B\C\D\E as ENamespace;
use
ENamespace\User;

new
User();
?>

> PHP 错误:未找到类“ENamespace\User”
0
thinice at gmail.com
13 年前
由于导入发生在编译时,因此在条件语句中嵌入 use 关键字不会产生多态性潜力。

例如

<?php
if ($objType == 'canine') {
use
Animal\Canine as Beast;
}
if (
$objType == 'bovine') {
use
Animal\Bovine as Beast;
}

$oBeast = new Beast;
$oBeast->feed();
?>
-2
dominic_mayers at yahoo dot com
7 年前
为了阐明在类中插入特征和在命名空间中导入特征之间的区别,以下是一个先导入特征再插入特征的示例。

<?php
namespace ns1;
trait
T {
static
$a = "In T";
}

namespace
ns2;
use
ns1\T; // 在命名空间 ns2 中导入特征 ns1\T 的名称
class C {
use
T; // 在类 C 中插入特征 T,使用导入的名称。
}

namespace
main;
use
ns2\C;
echo
C::$a; // In T;
-5
kelerest123 at gmail dot com
9 年前
对于第五个示例(示例 #5)

在块作用域中,这并非对 use 关键字的非法使用,因为它用于与特征共享内容。
-8
匿名
11 年前
本页面的最后一个示例展示了一种可能不正确的别名尝试,但导入特征 \Languages\Languages\Danish 则是完全正确的。
-3
info at ensostudio dot ru
3 年前
注意:您可以导入不存在的项目,不会出现错误。
<?php
use UndefinedClass;
use function
undefined_fn;
use const
UNDEFINED_CONST;
?>
但您无法使用/调用它们。
<?php
$new UndefinedClass
; // 错误:使用未定义的类
use function undefined_fn; // 错误:使用未定义的函数
use const UNDEFINED_CONST; // 错误:使用未定义的常量
?>
-11
Joey
6 年前
对于那些希望通过 {} 轻松解决 DRY 问题的人,很遗憾您无法嵌套它或对其进行任何酷炫的操作。您可以每个 use 语句中只使用一个,如果没有,则整个 use 语句都将被认为被括号包裹。这意味着,如果您确实使用了一个,您就不能像通常使用 use 一样使用 ,。

不可行

use A\B\C\{
D, E,
F\{X, Y, Z}
},
X\Y\Z,
H\{
I\{
Y\Y\Y\Y\Y,
Z, H, E
},
J\{
A\{
G\H\J
B\N
},
G\H\J
}
};
-3
tuxedobob
2 年前
请注意,由于这是在编译时处理的,所以在交互模式下运行 PHP 时它不起作用。use 命令不会抛出错误,但它们也不会执行任何操作。
-15
www.codewars.com
5 年前
太棒了!!

use function strval as numberToString;

var_dump(numberToString(123));

// 输出
// string(3) "123"
-9
Dhairya Lakhera
5 年前
namespace test{

use test\xyz\tikku;
use test\xyz\tikku as class_alias;
use function test\xyz\tikku\foo;
use function test\xyz\tikku\foo as func_alias;
use const test\xyz\tikku\ABC;
use const test\xyz\tikku\ABC as const_alias;




$obj=new tikku;
$obj->Display(); // 我在 test\xyz 命名空间中

$obj=new tikku\dhairya;
$obj->Display(); // 我在 test\xyz\tikku 命名空间中

$obj=new class_alias\dhairya;
$obj->Display(); // 我在 test\xyz\tikku 命名空间中

$obj=new \class_alias\dhairya;
$obj->Display(); // 我在 class_alias 命名空间中

}

namespace test\xyz{

class tikku{
function Display(){
echo "我在 ".__namespace__." 命名空间中<br/><hr/>";
}
}
}

namespace test\xyz\tikku{

class dhairya{
function Display(){
echo "我在 ".__namespace__." 命名空间中<br/><hr/>";
}
}
}

namespace class_alias{

class dhairya{
function Display(){
echo "我在 ".__namespace__." 命名空间中<br/><hr/>";
}
}
}
To Top