自研 PHP 框架 1.1_命名空间
命名空间
根据文档描述,命名空间设计的目标是用来解决命名冲突的。尤其是在多人合作的模式下,不可避免会出现命名冲突的问题。
命名空间原理类似 windows 系统下的文件夹,给每个用户创建一个文件夹,用户的所有文件都放在其所属的文件夹下,这些就可以将不同用户的文件彼此隔离开,只需要保证自己名下的文件名唯一,就不会产生命名冲突的问题。
格式要求
使用
namespace
关键字必须处于文件的最顶部,前面不能出现任何其他的字符(包括不可见的,空格,回车等),唯一的例外是 PHP 文件的声明标签
<?php
,其他的任何code
都不能在namespace
之前。<?php
namespace xxx;
多层级
命名空间可以嵌套多层(示例只列举了两层),实现类似文件夹嵌套的效果,每一层都是一个范围(域),同范围(域)的文件是可见的,不同层级的文件则不可见。
<?php
namespace first.econd;
作用域(变量的作用范围)
PHP 文件中变量只能在指定的范围内才存在,范围被划分为全局和局部,函数外是全局范围,函数内是局部范围。
<?php
$a = 10;
function test1()
{
$b = 10;
echo $a;
}
echo $b;
如上,$a
是全局变量,$b
是局部变量,彼此之间不可用(全局不能使用局部变量,局部不能使用全局变量)。
test1
中使用 $a
是不可以的,同样的,在全局使用 $b
也不可以。
作用域机制决定了变量只能在自己的域中才能被使用。
如果需要跨域使用变量,需要使用 global
关键字,将局部变量转变成全局变量之后才能使用。
具体使用
在 1.1 demo 版本中,引入了 namespace
的控制。
app/admin/controller/index.php
引入了命名空间
<?php
namespace app.dmin.ontroller;
class index
{
...
}
system/url.php
引入了命名空间
<?php
namespace system;
class url
{
...
}
添加了命名空间之后,当在 index.php
文件中引入这些文件
<?php
...
// 引入路由解析文件
include('./system/url.php');
...
// 加载指定文件
include(APP.$obj->get('path').EXT);
...
在使用这些引入文件中的类,接口,函数和常量时,就有了特别的要求(加了点东西,自然要和之前的情况不一样)。
这个时候如果以域的视角看,呈现的是下面这个样子(这是抽象出来的一种模型,有助于理解)
<?php
app
system
xxxx //这里是 index.php 中的逻辑处理部分
加了 namespace
的文件,不再可见(结合目录,可知 app
和 system
下都是有文件或文件夹的),现在被命名空间包裹了起来,如果命名空间有多个层级如 app.ontroller.ndex
,则会有多层包裹,这样在使用的时候就需要指明所要使用到的函数和类究竟在什么位置(类似于绝对路径)。
<?php
...
$obj = new app.ontroller.ndex.ndex();
如上,如果要创建一个 index
控制器下的 index
对象,就需要按照这样的写法,系统才能正确的进行定位。
入口文件 index.php
就是根域可见的一部分,其中的逻辑操作都视为根域下的操作。
当处于一个域之下时,如果不作特别说明,系统默认自带当前域前缀,看如下示例说明
入口文件index.php
<?php
$a = in_array(); //写法
---
$a = .n_array(); //实际解析时
应用控制器index.php
<?php
namespace app.dmin.ontroller;
$a = in_array(); //写法
$b = .n_array(); //这里显式指明使用系统函数
---
$a = .pp.dmin.ontroller.n_array(); //实际解析时
回到 namespace
的设计目标,其被设计用来解决命名冲突问题,解决的原理是分配不同的空间,各自在各自的空间内活动,彼此之间不可见,这样就避免了命名冲突的问题,这是其最重要的作用。
当然在使用时,必须按照正确的方式使用才能确保其生效。正如前面所说的域前缀的问题。
PS:本系列文章最佳阅读方式,IDE + 本地运行环境,IDE 中阅读可配合 demo 运行增进理解,GitHub 地址
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: