PHP的自动加载机制

PHP的自动加载机制

    最近尝试着写一个简单的php框架,来加深对mvc的认识,其中类的载入是首先要解决的问题。这篇文章,让我们追根溯源,看看类的加载如何从最原始的做法然后一步一步改进,到现在形成比较成熟的做法。来对类的载入有一个更加深刻的认识。

    1、面向过程式的做法

    整个项目里到处都是include或require

    

    缺点:难看、不易维护

    2、__autoload(魔术方法)

        autoload机制可以使得PHP程序在使用类时才自动包含文件,而不是一开始就将所有的类文件全部包含,这就是自动加载。

        当new一个类的时候,如果类不存在,则会调用此方法传入类名。

      参考代码:

 1 Tom.php
 2 <?php
 3 class Tom
 4 {
 5     public function say()
 6     {
 7         echo "Hello Tom." . PHP_EOL;
 8     }
 9 }
10 ?>
11 
12 Lily.php
13 <?php
14 class Lily
15 {
16     public function say()
17     {
18         echo 'Hello Lily.' . PHP_EOL;
19     }
20 }
21 ?>
22 
23 autoload.php
24 <?php
25 
26 function __autoload($classname)
27 {
28     $filename = "./" . $classname . ".php";
29     echo $classname . PHP_EOL;
30     include_once($filename);
31 }
32 
33 $tom = new Tom();
34 $lily = new Lily();
35 echo $tom->say();
36 echo $lily->say();

运行结果:

  

    缺点:一个项目中仅能有一个这样的 __autoload() 函数,因为 PHP 不允许函数重名,也就是说你不能声明2个__autoload()函数文件,否则会报致命错误。php7.2已经弃用__autoload函数。

    3、spl_autoload_register

         1) spl_autoload_register是可以多次重复使用的,这一点正是解决了__autoload的短板。

         2)注册的函数会进入队列中,多次注册时,先进先出,加载成功则终止,加载失败会继续调用队列中下一个被注册的函数。

       参考代码1:

 1 <?php
 2 
 3 class MyClass {
 4   public static function autoload($className) {
 5     // ...
 6   }
 7 }
 8 
 9 spl_autoload_register(array('MyClass', 'autoload'));
10 ?>
11 
12 * Or you can use an instance :
13 <?php
14 class MyClass {
15   public function autoload($className) {
16     // ...
17   }
18 }
19 
20 $instance = new MyClass();
21 spl_autoload_register(array($instance, 'autoload'));
22 ?>

 参考代码2:

 1 Lily.php
 2 <?php
 3 
 4 class Lily
 5 {
 6     public function say()
 7     {
 8         echo 'Hello Lily.' . PHP_EOL;
 9     }
10 }
11 ?>
12 <?php
13 /**
14  * spl_autoload_register($autoload_function, true, false)
15  * 第一个参数(autoload_function):欲注册的自动装载函数。
16  * 第二个参数(throw):此参数设置了 autoload_function 无法成功注册时, spl_autoload_register()是否抛出异常。
17  * 第三个参数(prepend):当为true时,spl_autoload_register()函数会添加函数到队列之首,而不是队列尾部。
18  */
19 spl_autoload_register('autoload', true, true);
20 
21 /**
22  * 自定义类加载
23  * @param string $className
24  */
25 function autoload($className="") {
26     echo "类名为:autoload/".$className . PHP_EOL;
27     include "./{$className}.php";
28 }
29 
30 $Lily = new Lily();
31 $Lily->say();
32 
33 //运行结果:
34 //类名为:autoload/Lily
35 //Hello Lily.

4、spl_autoload_register+namespace命名空间

    自动加载现在是PHP现代框架的基石,基本都是spl_autoload_register来实现自动加载。namespace也是使用比较多的。所以spl_autoload_register + namespace 就成为了一个主流

参考代码:

 1 Name.php
 2 <?php
 3 
 4 namespace Lib;
 5 
 6 class  Name
 7 {
 8     public static function test()
 9     {
10         echo '123';
11     }
12 }
13 ?>
14 loading.php
15 <?php
16 
17 namespace autoload;
18 
19 class loading
20 {
21     public static function autoload($className)
22     {
23         //根据PSR-O的第4点 把  转换层(目录风格符) DIRECTORY_SEPARATOR ,
24         //便于兼容Linux文件找。Windows 下(/ 和 )是通用的
25         //由于namspace 很规格,所以直接很快就能找到
26         $fileName = str_replace('\', DIRECTORY_SEPARATOR, DIR . '\' . $className) . '.php';
27         if (is_file($fileName)) {
28             require $fileName;
29         } else {
30             echo $fileName . ' is not exist';
31             die;
32         }
33     }
34 }
35 ?>
36 index.php
37 <?php
38 
39 //定义当前的目录绝对路径
40 define('DIR', dirname(__FILE__));
41 //加载这个文件
42 require DIR . '/loading.php';
43 //采用`命名空间`的方式注册。php 5.3 加入的
44 //也必须是得是static静态方法调用,然后就像加载namespace的方式调用,注意:不能使用use
45 spl_autoload_register("\autoload\loading::autoload");
46 // 调用三个namespace类
47 //定位到Lib目录下的Name.php
48 LibName::test();
49 
50 //运行结果:
51 //123

下一篇文章,我们尝试利用 Composer 来一步一步构建自己的 PHP 框架。

参考链接:
https://www.zybuluo.com/phper/note/66447
https://www.php.net/manual/zh/function.spl-autoload-register.php

原文地址:https://www.cnblogs.com/hld123/p/14205741.html