PHP命名空间(namespace)原理与用法详解

2025-05-27 0 90

本文实例讲述了PHP命名空间(namespace)原理与用法。分享给大家供大家参考,具体如下:

PHP 命名空间(namespace)是在PHP 5.3中加入的,它可以解决以下两类问题:

  1. 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
  2. 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

我们在默认情况下,所有常量、类和函数名都放在全局空间下,就和PHP支持命名空间之前一样,命名空间通过关键字namespace 来声明,如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间。我们来看下语法:

?

1

2

3

4
<?php

// 定义代码在 'MyProject' 命名空间中

namespace MyProject;

// ... 代码 ...

我们也可以在同一个文件中定义不同的命名空间代码,如下:

?

1

2

3

4

5

6

7

8

9

10
<?php

namespace MyProject;

const CONNECT_OK = 1;

class Connection { /* ... */ }

function connect() { /* ... */ }

namespace AnotherProject;

const CONNECT_OK = 1;

class Connection { /* ... */ }

function connect() { /* ... */ }

?>

不过我不建议使用这种语法在单个文件中定义多个命名空间,有需要的话,可以使用大括号形式的语法,如下:

?

1

2

3

4

5

6

7

8

9

10

11

12
<?php

namespace MyProject {

const CONNECT_OK = 1;

class Connection { /* ... */ }

function connect() { /* ... */ }

}

namespace AnotherProject {

const CONNECT_OK = 1;

class Connection { /* ... */ }

function connect() { /* ... */ }

}

?>

我们如果要将全局的非命名空间中的代码与命名空间中的代码组合在一起,只能使用大括号形式的语法,并且全局代码必须用一个不带名称的 namespace 语句加上大括号括起来,如下:

?

1

2

3

4

5

6

7

8

9

10

11

12
<?php

namespace MyProject {

const CONNECT_OK = 1;

class Connection { /* ... */ }

function connect() { /* ... */ }

}

namespace { // 全局代码

session_start();

$a = MyProject\\connect();

echo MyProject\\Connection::start();

}

?>

我们在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句,要记住,除了这个之外的所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前,如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13
<?php

declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码

namespace MyProject {

const CONNECT_OK = 1;

class Connection { /* ... */ }

function connect() { /* ... */ }

}

namespace { // 全局代码

session_start();

$a = MyProject\\connect();

echo MyProject\\Connection::start();

}

?>

看个错误的写法:

?

1

2

3

4
<html>

<?php

namespace MyProject; // 命名空间前出现了“<html>” 会致命错误 - 命名空间必须是程序脚本的第一条语句

?>

与目录和文件的关系很像,PHP 命名空间也允许指定层次化的命名空间的名称,因此,命名空间的名字可以使用分层次的方式定义,模式如下:

?

1

2

3

4

5

6
<?php

namespace MyProject\\Sub\\Level; //声明分层次的单个命名空间

const CONNECT_OK = 1;

class Connection { /* ... */ }

function Connect() { /* ... */ }

?>

上述代码中,创建了常量 MyProject\\Sub\\Level\\CONNECT_OK,类 MyProject\\Sub\\Level\\Connection 和函数 MyProject\\Sub\\Level\\Connect。

咱们再来看下PHP 命名空间中的类名的引用方式:

  1. 非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。 警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。
  2. 限定名称,或包含前缀的名称,例如 $a = new subnamespace\\foo(); 或 subnamespace\\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\\subnamespace\\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\\foo。
  3. 完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new \\currentnamespace\\foo(); 或 \\currentnamespace\\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespace\\foo。

咱们用来个文件来演示下,首先来看f1.php的代码:

?

1

2

3

4

5

6

7

8

9
<?php

namespace Foo\\Bar\\subnamespace;

const FOO = 1;

function foo() {}

class foo

{

static function staticmethod() {}

}

?>

之后就是f2.php的代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23
<?php

namespace Foo\\Bar;

include 'f1.php';

const FOO = 2;

function foo() {}

class foo

{

static function staticmethod() {}

}

/* 非限定名称 */

foo(); // 解析为函数 Foo\\Bar\\foo

foo::staticmethod(); // 解析为类 Foo\\Bar\\foo ,方法为 staticmethod

echo FOO; // 解析为常量 Foo\\Bar\\FOO

/* 限定名称 */

subnamespace\\foo(); // 解析为函数 Foo\\Bar\\subnamespace\\foo

subnamespace\\foo::staticmethod(); // 解析为类 Foo\\Bar\\subnamespace\\foo,

// 以及类的方法 staticmethod

echo subnamespace\\FOO; // 解析为常量 Foo\\Bar\\subnamespace\\FOO

/* 完全限定名称 */

\\Foo\\Bar\\foo(); // 解析为函数 Foo\\Bar\\foo

\\Foo\\Bar\\foo::staticmethod(); // 解析为类 Foo\\Bar\\foo, 以及类的方法 staticmethod

echo \\Foo\\Bar\\FOO; // 解析为常量 Foo\\Bar\\FOO

?>

我们访问任意全局类、函数或常量,都可以使用完全限定名称,例如 \\strlen() 或 \\Exception 或 \\INI_ALL。之后,咱们再来看下在命名空间内部访问全局类、函数和常量的实例:

?

1

2

3

4

5

6

7

8

9
<?php

namespace Foo;

function strlen() {}

const INI_ALL = 3;

class Exception {}

$a = \\strlen('hi'); // 调用全局函数strlen

$b = \\INI_ALL; // 访问全局常量 INI_ALL

$c = new \\Exception('error'); // 实例化全局类 Exception

?>

PHP 命名空间的实现受到其语言自身的动态特征的影响,我们先来看一段代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19
<?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

?>

我们如果要将上述的代码转换到命名空间中,并且动态访问元素,就必须使用完全限定名称(包括命名空间前缀的类名称)。注意因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠是不必要的。如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32
<?php

namespace namespacename;

class classname

{

function __construct()

{

echo __METHOD__,"\\n";

}

}

function funcname()

{

echo __FUNCTION__,"\\n";

}

const constname = "namespaced";

include 'example1.php';

$a = 'classname';

$obj = new $a; // 输出 classname::__construct

$b = 'funcname';

$b(); // 输出函数名

echo constant('constname'), "\\n"; // 输出 global

/* 如果使用双引号,使用方法为 "\\\\namespacename\\\\classname"*/

$a = '\\namespacename\\classname';

$obj = new $a; // 输出 namespacename\\classname::__construct

$a = 'namespacename\\classname';

$obj = new $a; // 输出 namespacename\\classname::__construct

$b = 'namespacename\\funcname';

$b(); // 输出 namespacename\\funcname

$b = '\\namespacename\\funcname';

$b(); // 输出 namespacename\\funcname

echo constant('\\namespacename\\constname'), "\\n"; // 输出 namespaced

echo constant('namespacename\\constname'), "\\n"; // 输出 namespaced

?>

好啦,本次记录就到这里了,后续的记录会在之后的文章中有体现。

希望本文所述对大家PHP程序设计有所帮助。

原文链接:https://blog.csdn.net/luyaran/article/details/82496414

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 PHP命名空间(namespace)原理与用法详解 https://www.kuaiidc.com/70884.html

相关文章

发表评论
暂无评论