PHP 命名空间
PHP 命名空间(namespace)是在PHP 5.3中加入的
定义命名空间
- 单个文件夹单个命名空间
// 定义代码在 'MyProject' 命名空间中
namespace MyProject;
// ... 代码 ...
- 单个文件夹多个命名空间
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
- 将全局的非命名空间中的代码与命名空间中的代码组合在一起
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // 全局代码
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
- 定义文件编码
在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。
declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码
namespace MyProject {
const CONNECT_OK = 1;
class Connection
{
static function start()
{
return 321;
}
}
function connect()
{
echo 123;
}
}
namespace { // 全局代码
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
子命名空间
namespace MyProject\Sub\Level; //声明分层次的单个命名空间
const CONNECT_OK = 1;
class Connection { /* ... */ }
function Connect() { /* ... */ }
命名空间使用
静态
file1.php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo()
{
echo "Foo\Bar\subnamespace 中的 foo";
}
class foo
{
static function staticmethod()
{
echo "Foo\Bar\subnamespace 中的 staticmethod";
}
}
file2.php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo()
{
echo "Foo\Bar 中的 foo";
}
class foo
{
static function staticmethod()
{
echo "Foo\Bar 中的 staticmethod";
}
}
以下操作在 file2.php
文件中操作
- 非限定名称,或不包含前缀的类名称
// 解析为函数 Foo\Bar\foo
foo(); // Foo\Bar 中的 foo
// 解析为类 Foo\Bar\foo ,方法为 staticmethod
foo::staticmethod(); // Foo\Bar 中的 staticmethod
// 解析为常量 Foo\Bar\FOO
echo FOO; // 2
- 限定名称,或包含前缀的名称
// 解析为函数 Foo\Bar\subnamespace\foo
subnamespace\foo(); // Foo\Bar\subnamespace 中的 foo
// 解析为类 Foo\Bar\subnamespace\foo, 类的方法 staticmethod
subnamespace\foo::staticmethod(); // Foo\Bar\subnamespace 中的 staticmethod
// 解析为常量 Foo\Bar\subnamespace\FOO
echo subnamespace\FOO; // 1
- 完全限定名称,或包含了全局前缀操作符的名称
// 解析为函数 Foo\Bar\foo
\Foo\Bar\foo(); // Foo\Bar 中的 foo
// 解析为类 Foo\Bar\foo, 以及类的方法 staticmethod
\Foo\Bar\foo::staticmethod(); // Foo\Bar 中的 staticmethod
// 解析为常量 Foo\Bar\FOO
echo \Foo\Bar\FOO; // 2
注意访问任意全局类、函数或常量,都可以使用完全限定名称
例如 \strlen() 或 \Exception 或 \INI_ALL。在命名空间内部访问全局类、函数和常量:
namespace Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // 调用全局函数strlen
$b = \INI_ALL; // 访问全局常量 INI_ALL
$c = new \Exception('error'); // 实例化全局类 Exception
动态
example1.php
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "global";
$a = 'classname';
$obj = new $a; // prints classname::__construct
$b = 'funcname';
$b(); // prints funcname
echo constant('constname'), "\n"; // prints global
example2.php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "namespaced";
include 'example1.php';
以下操作基于 example2.php
全局
$a = 'classname';
$obj = new $a; // 输出 classname::__construct
$b = 'funcname';
$b(); // 输出 funcname
echo constant('constname'), "\n"; // 输出 global
局部(namespaced)
$a = '\namespacename\classname';
$obj = new $a; // 输出 namespacename\classname::__construct
$b = '\namespacename\funcname';
$b(); // 输出 namespacename\funcname
echo constant('\namespacename\constname'), "\n"; // 输出 namespaced
$a = 'namespacename\classname';
$obj = new $a; // 输出 namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // 输出 namespacename\funcname
echo constant('namespacename\constname'), "\n"; // 输出 namespaced
namespace关键字 和 __NAMESPACE__常量
PHP支持两种抽象的访问当前命名空间内部元素的方法
- namespace
- __NAMESPACE__
1、常量 __NAMESPACE__ 的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它包含一个空的字符串。
namespace MyProject;
echo '"', __NAMESPACE__, '"'; // 输出 "MyProject"
echo '"', __NAMESPACE__, '"'; // 输出 ""
2、 常量 __NAMESPACE__ 在动态创建名称时很有用
namespace Foo\Bar;
const FOO = 2;
function foo()
{
echo "Foo\Bar 中的 foo";
}
class foo
{
static function staticmethod()
{
echo "Foo\Bar 中的 staticmethod";
}
}
$a = __NAMESPACE__ . '\\' .'foo';
$a(); // Foo\Bar 中的 foo
$b = __NAMESPACE__ . '\\' .'foo::staticmethod';
$b(); // Foo\Bar 中的 staticmethod
3、 namespace 可用来显式访问当前命名空间或子命名空间中的元素
namespace MyProject;
use blah\blah as mine; // 引入了 blah\blah 命名空间,并定义了个别名mine
mine\mine(); // 调用函数 blah\blah\mine()
namespace\blah\mine(); // 调用函数 MyProject\blah\mine()
使用命名空间:别名/导入
- 使用use操作符导入/使用别名
namespace foo;
use My\Full\Classname as Another;
// 下面的例子与 use My\Full\NSname as NSname 相同
use My\Full\NSname;
// 导入一个全局类
use \ArrayObject;
// 实例化 foo\Another 对象
$obj = new namespace\Another;
// 实例化 My\Full\Classname 对象
$obj = new Another;
// 调用函数 My\Full\NSname\subns\func
NSname\subns\func();
// 实例化 ArrayObject 对象
$a = new ArrayObject(array(1));
// 如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
- 一行中包含多个use语句
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 实例化 My\Full\Classname 对象
NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func
- 导入和动态名称
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 实例化一个 My\Full\Classname 对象
$a = 'Another';
$obj = new $a; // 实际化一个 Another 对象
- 导入和完全限定名称
use My\Full\Classname as Another, My\Full\NSname;
// 实例化 My\Full\Classname 类
$obj = new Another;
// 实例化 Another 类
$obj = new \Another;
// 实例化 My\Full\Classname\thing 类
$obj = new Another\thing;
// 实例化 Another\thing 类
$obj = new \Another\thing;
命名空间的顺序
namespace A;
use B\D, C\E as F;
- 函数调用
/*
首先尝试调用定义在命名空间"A"中的函数foo()
再尝试调用全局函数 "foo"
*/
foo();
// 调用全局空间函数 "foo"
\foo();
// 调用定义在命名空间"A\my"中函数 "foo"
my\foo();
/*
首先尝试调用定义在命名空间"A"中的函数 "F"
再尝试调用全局函数 "F"
*/
F();
- 类引用
/*
创建命名空间 "A" 中定义的类 "B" 的一个对象
如果未找到,则尝试自动装载类 "A\B"
*/
new B();
/*
使用导入规则,创建命名空间 "B" 中定义的类 "D" 的一个对象
如果未找到,则尝试自动装载类 "A\B"
*/
new D();
/*
使用导入规则,创建命名空间 "C" 中定义的类 "E" 的一个对象
如果未找到,则尝试自动装载类 "C\E"
*/
new F();
/*
创建定义在全局空间中的类 "B" 的一个对象
如果未发现,则尝试自动装载类 "B"
*/
new \B();
/*
创建定义在全局空间中的类 "D" 的一个对象
如果未发现,则尝试自动装载类 "D"
*/
new \D();
/*
创建定义在全局空间中的类 "F" 的一个对象
如果未发现,则尝试自动装载类 "F"
*/
new \F();
- 调用另一个命名空间中的静态方法或命名空间函数
// 调用命名空间 "A\B" 中函数 "foo"
B\foo();
/*
调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法
如果未找到类 "A\B" ,则尝试自动装载类 "A\B"
*/
B::foo();
/*
使用导入规则,调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法
如果类 "B\D" 未找到,则尝试自动装载类 "B\D"
*/
D::foo();
// 调用命名空间 "B" 中的函数 "foo"
\B\foo();
/*
调用全局空间中的类 "B" 的 "foo" 方法
如果类 "B" 未找到,则尝试自动装载类 "B"
*/
\B::foo();
- 当前命名空间中的静态方法或函数
/*
调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法
如果类 "A\A\B" 未找到,则尝试自动装载类 "A\A\B"
*/
A\B::foo();
/*
调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法
如果类 "A\B" 未找到,则尝试自动装载类 "A\B"
*/
\A\B::foo();