使用命名空间:别名/导入
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
允许通过别名引用或导入外部的完全限定名称,是命名空间的一个重要特征。这有点类似于在类 unix 文件系统中可以创建对其它的文件或目录的符号连接。
PHP 可以为这些项目导入或设置别名: 常量、函数、类、接口、trait、枚举和命名空间。
别名是通过操作符 use
来实现的。下面是五种导入方式的例子:
示例 #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; // class My\Full\Classname 的实例对象
$obj = new \Another; // class Another 的实例对象
$obj = new Another\thing; // class My\Full\Classname\thing 的实例对象
$obj = new \Another\thing; // class Another\thing 的实例对象
?>
导入规则的范围
use
关键词必须在文件最外层范围
(全局作用域)或在命名空间声明内。
由于导入发生在编译时,而不是运行时,所以不能放入块作用域。
以下例子展示了不合规则的 use
关键词使用示例:
示例 #5 不合规的导入规则
<?php
namespace Languages;
function toGreenlandic()
{
use Languages\Danish;
// ...
}
?>
注意:
导入规则独立于每个文件,意味着包含的文件 不会继承父文件的导入规则。
use
声明编组
通过单个 use
语句,可以将来自同一个 namespace
的
类、函数、常量一起编组导入。
<?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};
+添加备注
用户贡献的备注 17 notes
dominic_mayers at yahoo dot com ¶
8 years ago
The keyword "use" has been recycled for three distinct applications:
1- to import/alias classes, traits, constants, etc. in namespaces,
2- to insert traits in classes,
3- to inherit variables in closures.
This page is only about the first application: importing/aliasing. Traits can be inserted in classes, but this is different from importing a trait in a namespace, which cannot be done in a block scope, as pointed out in example 5. This can be confusing, especially since all searches for the keyword "use" are directed to the documentation here on importing/aliasing.
anon ¶
11 years ago
The <?php use ?> statement does not load the class file. You have to do this with the <?php require ?> statement or by using an autoload function.
Mawia HL ¶
7 years ago
Here is a handy way of importing classes, functions and conts using a single use keyword:
<?php
use Mizo\Web\ {
Php\WebSite,
Php\KeyWord,
Php\UnicodePrint,
JS\JavaScript,
function JS\printTotal,
function JS\printList,
const JS\BUAIKUM,
const JS\MAUTAM
};
?>
k at webnfo dot com ¶
11 years ago
Note that you can not alias global namespace:
use \ as test;
echo test\strlen('');
won't work.
xzero at elite7hackers dot net ¶
7 years ago
I couldn't find answer to this question so I tested myself.
I think it's worth noting:
<?php
use ExistingNamespace\NonExsistingClass;
use ExistingNamespace\NonExsistingClass as whatever;
use NonExistingNamespace\NonExsistingClass;
use NonExistingNamespace\NonExsistingClass as whatever;
?>
None of above will actually cause errors unless you actually try to use class you tried to import.
<?php
// And this code will issue standard PHP error for non existing class.
use ExistingNamespace\NonExsistingClass as whatever;
$whatever = new whatever();
?>
me at ruslanbes dot com ¶
8 years ago
Note the code `use ns1\c1` may refer to importing class `c1` from namespace `ns1` as well as importing whole namespace `ns1\c1` or even import both of them in one line. Example:
<?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) { }
c dot 1 at smithies dot org ¶
13 years ago
If you are testing your code at the CLI, note that namespace aliases do not work!
(Before I go on, all the backslashes in this example are changed to percent signs because I cannot get sensible results to display in the posting preview otherwise. Please mentally translate all percent signs henceforth as backslashes.)
Suppose you have a class you want to test in myclass.php:
<?php
namespace my%space;
class myclass {
// ...
}
?>
and you then go into the CLI to test it. You would like to think that this would work, as you type it line by line:
require 'myclass.php';
use my%space%myclass; // should set 'myclass' as alias for 'my%space%myclass'
$x = new myclass; // FATAL ERROR
I believe that this is because aliases are only resolved at compile time, whereas the CLI simply evaluates statements; so use statements are ineffective in the CLI.
If you put your test code into test.php:
<?php
require 'myclass.php';
use my%space%myclass;
$x = new myclass;
//...
?>
it will work fine.
I hope this reduces the number of prematurely bald people.
x at d dot a dot r dot k dot REMOVEDOTSANDTHIS dot gray dot org ¶
12 years ago
You are allowed to "use" the same resource multiple times as long as it is imported under a different alias at each invocation.
For example:
<?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;
...
?>
In the above example, "Keller", "Stellar", and "Zellar" are all references to "\Lend\l1\Keller", as are "Lend\l1\Keller", "l1\Keller", and "l3\Keller".
cl ¶
11 years ago
Something that is not immediately obvious, particular with PHP 5.3, is that namespace resolutions within an import are not resolved recursively. i.e.: if you alias an import and then use that alias in another import then this latter import will not be fully resolved with the former import.
For example:
use \Controllers as C;
use C\First;
use C\Last;
Both the First and Last namespaces are NOT resolved as \Controllers\First or \Controllers\Last as one might intend.
ultimater at gmail dot com ¶
8 years ago
Note that "use" importing/aliasing only applies to the current namespace block.
<?php
namespace SuperCoolLibrary
{
class Meta
{
static public function getVersion()
{
return '2.7.1';
}
}
}
namespace
{
use SuperCoolLibrary\Meta;
echo Meta::getVersion();//outputs 2.7.1
}
namespace
{
echo Meta::getVersion();//fatal error
}
?>
To get the expected behavior, you'd use:
class_alias('SuperCoolLibrary\Meta','Meta');
ZhangLiang ¶
8 years ago
In Chinese,there is an error in translation:
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
it should be
// 如果不使用 "use ArrayObject" ,则实例化一个 foo\ArrayObject 对象
/*********************************************/
中文下翻译有错误
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
这句话应该是
// 如果不使用 "use ArrayObject" ,则实例化一个 foo\ArrayObject 对象
eithed at google mail ¶
3 years ago
Bear in mind that it's perfectly fine to alias namespaces, ie:
<?php
use A\B\C\D\E\User;
new User();
?>
can be also written as:
<?php
use A\B\C\D\E as ENamespace;
new ENamespace\User();
?>
however following will not work:
<?php
use A\B\C\D\E as ENamespace;
use ENamespace\User;
new User();
?>
> PHP Error: Class "ENamespace\User" not found
thinice at gmail.com ¶
14 years ago
Because imports happen at compile time, there's no polymorphism potential by embedding the use keyword in a conditonal.
e.g.:
<?php
if ($objType == 'canine') {
use Animal\Canine as Beast;
}
if ($objType == 'bovine') {
use Animal\Bovine as Beast;
}
$oBeast = new Beast;
$oBeast->feed();
?>
dominic_mayers at yahoo dot com ¶
8 years ago
To clarify the distinction between inserting a trait in a class and importing a trait in a namespace, here is an example where we first import and then insert a trait.
<?php
namespace ns1;
trait T {
static $a = "In T";
}
namespace ns2;
use ns1\T; // Importing the name of trait ns1\T in the namespace ns2
class C {
use T; // Inserting trait T in the class C, making use of the imported name.
}
namespace main;
use ns2\C;
echo C::$a; // In T;
kelerest123 at gmail dot com ¶
9 years ago
For the fifth example (example #5):
When in block scope, it is not an illegal use of use keyword, because it is used for sharing things with traits.
info at ensostudio dot ru ¶
4 years ago
Note: you can import not existed items without errors:
<?php
use UndefinedClass;
use function undefined_fn;
use const UNDEFINED_CONST;
?>
but you cant use/call they:
<?php
$new UndefinedClass; // Error: Use of undefined class
use function undefined_fn; // Error: Use of undefined function
use const UNDEFINED_CONST; // Error: Use of undefined constant
?>
备份地址:http://www.lvesu.com/blog/php/language.namespaces.importing.php