加入收藏 | 设为首页 | 会员中心 | 我要投稿 91站长网 (https://www.91zhanzhang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php类的命名空间与自动加载

发布时间:2022-10-18 15:01:10 所属栏目:PHP教程 来源:网络
导读: 命名空间的作用:
1. 解决开发者自定义的类/函数/常量 与 第三方类/函数/常量 之间的命名冲突;
比方说你写了个文章类叫Article,由于业务需要下载第三方扩展库,好巧不巧扩展库中也有个文

命名空间的作用:

1. 解决开发者自定义的类/函数/常量 与 第三方类/函数/常量 之间的命名冲突;

比方说你写了个文章类叫Article,由于业务需要下载第三方扩展库,好巧不巧扩展库中也有个文章类叫Article;

这下好了,假如在编码过程中同时引入了这两类,就会导致php认为你重复引用两个Article类,php就不干了,然后抛出错误:Fatal error: Cannot redeclare Article (previously declared)PHP命名空间,接着程序就挂了。

使用了命名空间后,就需要写的复杂一些,不过好处是规范了所处位置,也解决了命名冲突。上述自己写的文章类就可以定义为 namespace my\Article ,如果你觉得不爽也可以写成 namespace test\Article 或者 namespace aaa\Articel等等其余任何形式;而第三方扩展库都会遵循规范有自己的命名空间(这个不需要你担心,一般不会和你写的命名空间冲突),这样就解决了命名冲突的问题。

2.给类起个别名,缩短类名,提升代码可读性

像上面的namespace my\Article算是比较短的命名空间,复杂点的像thinkphp一样:app\Controller\Article,同时在Article类下又有个show方法,想要调用show方法,就得去new app\Controller\Article,然后再->show(),如下:

<?php
use app\Controller\Article;
$article = new Article;
$article->show();

上面虽然功能是可以实现,但是拿这么一大串去调用未免看得太过疲劳,于是我们可以给这个命名空间起个别名,缩短一下代码量,看起来显得更舒服。如下:

<?php
use app\Controller\Article as As;
$article = new As;
$article->show();

当依赖的类越来越多的时候,起别名的方式就显得极其重要,提升了代码可读性,也减少了开发者的编码量。

自动加载的作用:

在php5.3以前没有出现自动加载的时候,要使用一个类,还得手动使用require/inlcude去把该类引入进当前文件中,否则就会抛出错误:没找到这个类/这个类未定义。这样做极其麻烦(不信你引入100个php类文件试试?),所以自动加载应运而生了,而意义就是使得原本开发者需要手动引入的类转变成自动引入!产生了一个名为__autoload的自动加载方法,用于解决该项问题。

举个例子,当在index.php文件中调用atilce类中的show方法时,可以看到这里是没有去require 'article.php'这个类文件的,而是使用了__autoload自动加载函数去自动的require该类。

整体逻辑:实例化article类->php发现该类未定义->触发__autoload自动加载方法>获取到未定义的类名入参->在类名参数后拼接php文件后缀组成完整类文件->require 类文件

假如有100个类文件需要依赖,通过这种方式就可以自动进入到__autoload中加载,而不需要写100条require...

PHP命名空间_php命名空间的使用_php 驼峰命名 正则

运行结果:

自动加载的更新:

通过__autoload我们知道可以利用该方法去帮助我们处理未定义的类进行引入,这也是php自动加载的魅力所在。但是__autoload有个弊端:只可以声明一次(只能有一个),这样会带来什么坏处呢?

刚刚可以看到要引入的article类和index.php所处同一级,还是和刚刚一样,假如一共需要引入100个类文件。20个在index.php的上一级,另外60个在index.php的上上级,其余19个在在index.php的上上上级,它们所处的文件位置与index.php不同级,但是又需要引入,那么就会导致逻辑判断的复杂性一下子增加了,要根据不同的层级去引入不同的文件,所有逻辑代码全都堆积在__autoload函数中,可读性也会变得更差。具体如下图:

php命名空间的使用_php 驼峰命名 正则_PHP命名空间

这也是为什么__autoload在php7.2中被废弃的原因,弊端太明显了,php吸取了该缺陷,进而推出了新的自动加载类函数spl_autoload_register。该函数在继承了__autoload方法的优点后,又吸取了之前的教训,可以实现多种注册机制的加载方式(相较于__autoload方法,该函数更加灵活,且逻辑拆分的更为细致),不像__autoload一样只能定义一次要处理所有逻辑。

有了spl_auotload_register函数,就可以将不同的加载机制分别抽离,更直观的处理对应的加载逻辑以及可以实现多种注册机制,优化如下:

PHP命名空间_php命名空间的使用_php 驼峰命名 正则

命名空间与自动加载的结合实践:

讲完了上述的命名空间与自动加载知识后,终于来到了这里;像thinkphp这等传统php框架所使用的是这一套流程,在入口文件中引入一个自动加载类,并在该加载类中使用spl_autoload_register等函数自动加载所需类,接下来就来模拟实现来一下。

目录结构左侧已圈出,可以看到和tp的目录结构是一致的。

当访问index.php入口文件时,首先引入了一个loader.php的自动加载类(这个类第一件事就注册了spl_autoload_register函数,以便当php发现有类未定义时立马回调到Loader方法中,拼接php后缀组成类文件并引入该类文件),然后引入了控制器下的Video类和Article类的命名空间(这很合理,表名了文件所在位置),接着就是调用这两控制器下不同的静态方法(为了区分,一个我写成了shows,另一个写成了show),随后调用了Video下的普通方法show。

php命名空间的使用_PHP命名空间_php 驼峰命名 正则

让我们来看看结果如何:

PHP命名空间_php 驼峰命名 正则_php命名空间的使用

很明显index.php的三个方法都已经调用完毕并且成功输出了,这样一个简单的命名空间与自动加载结合的案例就完成了。

这里要补充说明一些知识,同时也是笔者曾犯过的思维误区:

重要的事情说三遍:

use只是表明了依赖类所在的命名空间,并不具备引入对应类文件的能力!

use只是表明了依赖类所在的命名空间,并不具备引入对应类文件的能力!

use只是表明了依赖类所在的命名空间,并不具备引入对应类文件的能力!

虽然在tp中使用use即可引入依赖类,但是底层实际上还是通过require/include函数去引入加载了对应命名空间的文件(实际上干活的是require/include)。也就是说use和自动加载是配套使用的,use负责表明依赖类文件所处的命名空间,而自动加载负责根据use表明的依赖类所处的命名空间,以正确的路径引入该文件至当前类文件中,以便调用。

说了这么多,笔者想说明的是:在tp中使用use依赖类就可以使用依赖类的功能,请不要以为这是use关键字具备的能力(不是!不是!不是!),实际上干活的还是自动加载函数!!!

参考资料:

php自动加载为什么autoload被抛弃了

PHP中use关键字的作用有哪些

php中的use有什么作用

(编辑:91站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!