zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Redis源代码分析(十三)--- redis-benchmark性能測试
    kvm中运行kvm
    umount.nfs device busy day virsh extend diskSpace, attachDisk
    ultravnc
    openNebula dubug
    maintenance ShellScripts
    virsh VMI deploy data serial xml
    cloud computing platform,virtual authentication encryption
    基于C 的libvirt 接口调用
    storage theory
  • 原文地址:https://www.cnblogs.com/hld123/p/14205741.html
Copyright © 2011-2022 走看看