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

  • 相关阅读:
    C#全角半角转换输出解决方法
    screen命令
    Parrot Linux国内源
    screen命令在freebsd安装和使用
    sysbench0.5 在 centos7下安装 (mysql-community-server)
    Mysql中文乱码问题完美解决方案
    PHP返回数据被nginx截断问题的解决方法
    yii2笔记:asset压缩js,css文件
    Yii2笔记:activerecord和activecontroller
    yii2笔记: 模块(module)
  • 原文地址:https://www.cnblogs.com/hld123/p/14205741.html
Copyright © 2011-2022 走看看