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

(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

up
194
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.
up
156
anon
10 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.
up
56
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
};
?>
up
80
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.
up
33
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();
?>
up
23
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) { }
up
28
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.
up
20
x at d dot a dot r dot k dot REMOVEDOTSANDTHIS dot gray dot org
11 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".
up
16
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.
up
3
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');
up
1
ZhangLiang
7 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 对象
up
0
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
up
0
thinice at gmail.com
13 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();
?>
up
-2
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;
up
-5
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.
up
-3
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
?>
up
-3
tuxedobob
2 years ago
Note that because this is processed at compile time, this doesn't work when running PHP in interactive mode. use commands won't throw an error, but they won't do anything, either.
To Top