关于PHP的命名空间实例详解

什么是PHP命名空间

PHP手册:从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。

命名空间的作用

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

 

 

示例

1. 例一 
首先我们先建立两个类文件 
a.php

1

2

3

4

5

6

class Test{

    public function test()

    {

      echo "this is A class.";

    }

}

b.php

1

2

3

4

5

6

class Test{

    public function test()

    {

       echo "this is B class.";

    }

}

再建立一个index.php文件,来引入以上两个类并调用其中的方法。 
index.php

1

2

require_once("a.php");

require_once("b.php");

现在运行index.php文件,你会发现有一个致命错误: Fatal error: Cannot redeclare class Test in。。。很显然,无法重新声明Test类,因为你引入了两次,而且两个文件中的类名称相同,冲突了。这个时候就需要命名空间来解决这个问题,并且很容易。 
2. 例二 
我们现在把两个类文件稍作修改。 
a.php

1

2

3

4

5

6

namespace a\test;class Test{

    public function test()

    {

        echo "this is A class.";

    }

}

b.php

1

2

3

4

5

6

7

namespace b\test;

  class Test{

    public function test()

    {

       echo "this is B class.";

    }

}

namespace关键字是用来声明命名空间的。现在运行index.php发现没有错误,修改index.php进行方法调用测试 
index.php

1

2

3

4

require_once("a.php");

require_once("b.php");

$a = new a\test\Test();

$a->test();//页面输出:this is A class.

3. 例三 
现在有另外一种情况,比如我需要实例化a.php中的Test类多次,那么每次我们都需要命名空间信息完整写的话比较麻烦怎么办呢?比如: 
index.php

1

2

3

4

5

6

7

require_once("a.php");

require_once("b.php");

$a = new a\test\Test();

$a_a = new a\test\Test();

$a_b = new a\test\Test();

$a->test(); //页面输出:this is A class.

$a_a->test();//页面输出:this is A class.

虽然也没有错误,但是你会发现比较麻烦,每次都需要全写命名空间名称,虽然不报错并且可以ctrl+c,ctrl+v,但是不太美观(^_^)。 
你可以这样做: 
index.php

1

2

3

4

5

6

7

8

require_once("a.php");

require_once("b.php");

use a\test\Test;

$a = new Test();

$a_a = new Test();

$a_b = new Test();

$a->test();//页面输出:this is A class.

$a_a->test();//页面输出:this is A class.

use关键字是用来引入类,用命名空间的方式表示使用了某个类。后面就可以直接实例化操作。
4. 例五 
接下来另一个问题又来了,如下: 
index.php

1

2

3

4

5

6

7

8

require_once("a.php");

require_once("b.php");

use a\test\Test;

use b\test\Test;

$a = new Test();

$b = new Test();

$a->test();

$b->test();

很明显,又一个致命错误:Fatal error: Cannot use b\test\Test as Test because the name is already in use in 。。。因为虽然使用了命名空间,但是两个类名称相同,都是Test,程序不知道第二个Test类是b.php中的Test类,这时候你就用到了as关键字完美解决。
如: 
index.php

1

2

3

4

5

6

7

8

require_once("a.php");

require_once("b.php");

use a\test\Test;

use b\test\Test as BTest;

$a = new Test();

$b = new BTest();

$a->test();//页面输出:this is A class.

$b->test();//页面输出:this is B class.

as关键字是对类名称定义别名,可以有效防止类名称相同冲突 
5. 例六 
下面是另一种情况,我先给出几个代码片段,是Yii2框架中的,和框架无关,只是为了演示使用,很多地方都能见到此例。

1

2

3

4

if (\Yii::$app->request->isPost) {

  $post = \Yii::$app->request->post();  

      ......

  }

很显然这里使用了一个Yii类,但是为什么前面又一个反斜杠”\”,我们先追踪一下Yii类,有的同学会问怎么追踪呢,如果你使用的是PHPstorm编辑器,直接按住Ctrl,鼠标点击类名就会跳到此类类文件中,关于怎么使用PHPstorm编辑器,请查看:PhpStorm破解版及使用教程 
下面是Yii类文件代码段:

1

2

3

4

5

6

7

8

9

/**

 * Yii bootstrap file.

 *

 * @link http://www.yiiframework.com/

 * @copyright Copyright (c) 2008 Yii Software LLC

 * @license http://www.yiiframework.com/license/

 */require(__DIR__ . '/BaseYii.php');

class Yii extends \yii\BaseYii{

}

你会发现该Yii类并没有命名空间,我们将这种类叫做全局类,如果要使用需要类前面加入反斜杠”\” 
比如我们在a.php同级再建立一个全局类文件:c.php:

1

2

3

4

5

6

class Test{

 public function test()

  {

   echo "this is C class.";

  }

}

在index.php文件中这样做即可调用c.php中的test方法

1

2

3

4

5

6

7

8

9

10

11

12

require_once("a.php");

require_once("b.php");

require_once("c.php");

 //页面输出:this is C class.

use a\test\Test;

use b\test\Test as BTest;

$a = new Test();

$b = new BTest();

$c = new \Test();

$a->test();//页面输出:this is A class.

$b->test();//页面输出:this is B class.

$c->test();//页面输出:this is C class.

注意:namespace,use,as等关键字用法以及全局类的使用。

 

 

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

 

<?php
namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace {    // 全局代码
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

 

在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。

 

<?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();
}
?>

 

以下代码会出现语法错误:

 

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

亲测:


 

 

 

 

 

 

 

 

 

 

 



posted @   李若盛开  阅读(420)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示