关键字“use”已被用于三种不同的应用场景
1- 在命名空间中导入/别名类、trait、常量等,
2- 在类中插入 trait,
3- 在闭包中继承变量。
此页面仅关于第一个应用:导入/别名。trait可以插入到类中,但这与在命名空间中导入trait不同,后者不能在块作用域中完成,如示例5所示。这可能会造成混淆,尤其是在所有对关键字“use”的搜索都指向此处关于导入/别名的文档时。
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
能够用别名引用外部全限定名或进行导入是命名空间的一个重要特性。这类似于基于unix的文件系统创建指向文件或目录的符号链接的能力。
PHP可以为常量、函数、类、接口、trait、枚举和命名空间创建别名/导入。
别名是使用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 函数
?>
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- 在命名空间中导入/别名类、trait、常量等,
2- 在类中插入 trait,
3- 在闭包中继承变量。
此页面仅关于第一个应用:导入/别名。trait可以插入到类中,但这与在命名空间中导入trait不同,后者不能在块作用域中完成,如示例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 ExistingNamespace\NonExsistingClass as whatever;
$whatever = new whatever();
?>
请注意,代码`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;
//...
?>
它将正常工作。
我希望这能减少过早秃顶的人数。
只要在每次调用时都使用不同的别名导入,就可以多次“使用”相同的资源。
例如
<?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 对象
/*********************************************/
Chinese translation is incorrect.
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
The correct sentence should be:
// 如果不使用 "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();
?>
为了阐明在类中插入 trait 和在命名空间中导入 trait 之间的区别,以下是一个先导入然后插入 trait 的示例。
<?php
namespace ns1;
trait T {
static $a = "In T";
}
namespace ns2;
use ns1\T; // 在命名空间 ns2 中导入 trait ns1\T 的名称
class C {
use T; // 在类 C 中插入 trait 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; // 错误:使用未定义的常量
?>