php怎么实现类的自动注册

2021-07-23 23:07:29 188

命名空间

  • 命名空间其实就是给文件起了一个虚拟的目录(一般和目录保持一致),如果没有命名空间,那么你载入的多个文件后,其实就相当于多个文件的代码全部融入到了一个文件,那么对于重复命名的方法,就会报错

报错信息PHP Fatal error: Cannot redeclare test() (previously declared in /Users/zhangguofu/website/default/IMooc/Test/Test1.php:9) in /Users/zhangguofu/website/default/IMooc/Test/Test2.php on line 12

Test1文件已经声明了test方法,Test2就不能声明了

image.png

那我们吧命名空间给加上去,看看怎么样,发现执行成功了,而在每个调用test函数前,都加上了各自的命名空间。这就是命名空间的作用

  • 但是我们也发现一个问题,每当要使用某个文件里面的方法,都必须要require一次,很麻烦,于是我们就发明了一个函数 __autoload,实现类的自动载入,当一个类被用到而没有被载入的话,这个函数就会试图载入这个类文件,举个栗子看一下。

  • 我们使用autoload(该函数在7.2以后已经被弃用) 函数加载类

image.png
  • 我用php5.6执行一下
guofu@guofu:/home/wwwroot/default/Example$ /usr/local/php5.6/bin/php demo_class.php
Test\Test1\T_Class
PHP Fatal error:  Class 'Test\Test1\T_Class' not found in /home/wwwroot/default/Example/demo_class.php on line 9
  • 此处需要注意一下,命名空间要和目录保持一致,类名要和文件名保持一致,这样才可以映射到相关的文件,同时也是PSR-0的规范
  • PSR-0规范 1.php的命名空间必须和路径保持一致 2.类名的首字母必须大写 3.除了入口文件之外,其他的php文件必须是只有一个类,而不能有其他的可执行代码
image.png

下面我们来执行一下

guofu@guofu:/home/wwwroot/default/Example$ /usr/local/php5.6/bin/php demo_class.php
Test\T_Class::t1
Test\T2_Class::t1
guofu@guofu:/home/wwwroot/default/Example$ 
  • __autoload 实现了类的自动装载机制,使得php在使用到该类时才自动包含类文件,而不是一开始就全部加载进来。这种机制就是 lazy loading

它有以下优点

  1. 使用类的时候不需要手动去include或者require 2.由于这种lazy loading ,避免了require多余的文件 3.无需考虑到文件的实际地址,我们根据命名空间就可以实现文件载入。
  • 但是这样会有一个问题,我们知道function __autoload($class)它是一个函数,那么这种函数, autoload () 是全局函数只能定义一次,不够灵活,所以所有的类名与文件名对应的逻辑规则都要在一个函数里面实现,造成这个函数的臃肿。,就没法实现了,怎么办呢?在php5.3以后spl_autoload_register() 满足了此类需求。我们来看一下效果

  • 或者使用匿名函数

<?php
/**
 * Notes:
 * User: zhangguofu
 * Date: 2021/7/23
 * Time: 下午6:24
 * Class ${NAME}
 */

//注意,这个自动加载应该放在类的调用前面
spl_autoload_register(function ($class){
 require_once (str_replace("\\","/",__DIR__."/".$class.".php"));
});
\Test\T_Class::t1();
echo PHP_EOL;
\Test\T2_Class::t1();

  • 多个函数也是可以的

有好奇心的同学可能会问spl_autoload_register 是怎么实现的呢? spl_autoload_register 函数的功能就是把传入的函数(参数可以为回调函数或函数名称形式)注册到 SPL __autoload 函数队列中,并移除系统默认的 __autoload() 函数。

一旦调用 spl_autoload_register() 函数,当调用未定义类时,系统就会按顺序调用注册到 spl_autoload_register() 函数的所有函数,而不是自动调用 __autoload() 函数。

  • 那么我们先了解一下上面是spl,SPL 是 Standard PHP Library (标准 PHP 库) 的缩写。它是 PHP5 引入的一个扩展库,这个库也实现了一些常见的数据结构,比如 队列 栈 堆 ,固定长度的数组等功能,想深入的同学可以去官网做进一步了解