关键字“use”已被循环使用于三个不同的应用程序
1- 在命名空间中导入/别名类、特征、常量等,
2- 在类中插入特征,
3- 在闭包中继承变量。
此页面仅介绍第一个应用程序:导入/别名。特征可以插入类,但这与在命名空间中导入特征不同,在命名空间中导入特征不能在块作用域中完成,如示例 5 所示。这可能会令人困惑,尤其是在所有搜索关键字“use”都指向此处有关导入/别名的文档时。
(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};
关键字“use”已被循环使用于三个不同的应用程序
1- 在命名空间中导入/别名类、特征、常量等,
2- 在类中插入特征,
3- 在闭包中继承变量。
此页面仅介绍第一个应用程序:导入/别名。特征可以插入类,但这与在命名空间中导入特征不同,在命名空间中导入特征不能在块作用域中完成,如示例 5 所示。这可能会令人困惑,尤其是在所有搜索关键字“use”都指向此处有关导入/别名的文档时。
以下是如何使用单个“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
};
?>
我找不到这个问题的答案,所以我自己测试了一下。
我认为值得注意的是
<?php
use ExistingNamespace\NonExsistingClass;
use ExistingNamespace\NonExsistingClass as whatever;
use NonExistingNamespace\NonExsistingClass;
use NonExistingNamespace\NonExsistingClass as whatever;
?>
除非您实际尝试使用您尝试导入的类,否则上述代码都不会实际导致错误。
<?php
// 这段代码将发出标准 PHP 错误,因为类不存在。
请注意,代码“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) { }
如果您在 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;
//...
?>
它将正常运行。
我希望这能减少过早秃头的人数。
只要每次调用都在不同的别名下导入,您就可以多次“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”一样。
有一点并非显而易见,尤其是在 PHP 5.3 中,即导入内的命名空间解析不会递归解析。即:如果您为一个导入创建别名,然后在另一个导入中使用该别名,那么这个后者的导入将不会与前者的导入完全解析。
例如
use \Controllers as C;
use C\First;
use C\Last;
First 和 Last 命名空间都不会像您预期的那样解析为 \Controllers\First 或 \Controllers\Last。
请注意,“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');
在中文中,翻译存在错误
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
应该是
// 如果不使用 "use ArrayObject" ,则实例化一个 foo\ArrayObject 对象
/*********************************************/
中文下翻译有错误
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
这句话应该是
// 如果不使用 "use ArrayObject" ,则实例化一个 foo\ArrayObject 对象
请记住,为命名空间创建别名完全没问题,例如
<?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”
由于导入发生在编译时,因此在条件语句中嵌入 use 关键字不会产生多态性潜力。
例如
<?php
if ($objType == 'canine') {
use Animal\Canine as Beast;
}
if ($objType == 'bovine') {
use Animal\Bovine as Beast;
}
$oBeast = new Beast;
$oBeast->feed();
?>
为了阐明在类中插入特征和在命名空间中导入特征之间的区别,以下是一个先导入特征再插入特征的示例。
<?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;
注意:您可以导入不存在的项目,不会出现错误。
<?php
use UndefinedClass;
use function undefined_fn;
use const UNDEFINED_CONST;
?>
但您无法使用/调用它们。
<?php
$new UndefinedClass; // 错误:使用未定义的类
use function undefined_fn; // 错误:使用未定义的函数
use const UNDEFINED_CONST; // 错误:使用未定义的常量
?>
对于那些希望通过 {} 轻松解决 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
}
};
太棒了!!
use function strval as numberToString;
var_dump(numberToString(123));
// 输出
// string(3) "123"
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/>";
}
}
}