PHP 的自动加载(持续学习更新中)

什么是自动加载

PHP 只能执行当前文件中的代码,但现代的工程化项目,都是由很多人的一起协作组成,不可能将所有代码写到一个文件中。那么,将其他人的代码包含到当前文件中,就是加载。区别于使用 require_once()require 等方法的手动加载,不进行显式加载的方式就是自动加载。PHP 中访问不存在的类时会调用 __autoload()

require 和 require_once 是怎么工作的

结论requirerequire_once 就是把对应文件的代码放置到调用这 2 个方法的位置。

验证
目录结构

- AnotherIndexClass.php
- index.php
- IndexClass.php

AnotherIndexClass.php

<?php

require_once 'IndexClass.php';
$indexClass->sayHello();

index.php

<?php

require_once 'IndexClass.php';

echo __FILE__ . ' : ' . __LINE__ . PHP_EOL;
$indexClass = new IndexClass();
require_once 'AnotherIndexClass.php';

IndexClass.php

<?php

require_once 'index.php';

class IndexClass
{
    public function __construct()
    {
        echo self::class . ' - ' . __FUNCTION__ . PHP_EOL;
    }

    public function sayHello()
    {
        echo self::class . ' - ' . __FUNCTION__ . PHP_EOL;
    }
}

echo __FILE__ . ' : ' . __LINE__ . PHP_EOL;

执行:php index.php
PHP 的自动加载(持续学习更新中)

可以看到,因为是在 index.php 中引入的 IndexClass.php,所以会先跑 IndexClass.php 中的代码,同时 AnotherIndexClass.php 中可以访问 index.php 中的变量($indexClass),就好像将所有代码都糅合到了一个文件中,然后按顺序在执行。

执行:php IndexClass.php
PHP 的自动加载(持续学习更新中)
可以看到,执行 php IndexClass.php 会和之前 php index.php 得到不一样的输出。也同样可以理解为将所有代码糅合到一个文件中,只不过之前是糅合到 index.php 中,而现在是糅合到 IndexClass.php 中。

require 和 require_once 的区别

require_once 会判断之前有没有引入过,就是因为加入了这个判断,require_once 的效率会要比 require 低很多。但同时,如果使用 require,就很容易造成相互引用而陷入死循环。比如将上面 3 个文件中的 require_once 都替换为 reuqire,我们会得到以下的输出。

PHP 的自动加载(持续学习更新中)

即,什么都不会执行,陷入了引用地狱。

访问不存在的类时会怎么样

校验代码

<?php

function __autoload($className) {
    echo ("from autoload:" . $className . PHP_EOL);
}

spl_autoload_register(function ($className) {
    echo ("from spl - 1:" . $className . PHP_EOL);
});

spl_autoload_register(function ($className) {
    echo ("from spl - 2:" . $className . PHP_EOL);
});

$notExist = new AnotherNotExist();

PHP 的自动加载(持续学习更新中)

要点说明

  1. 方框1:__autoload() 函数已不建议使用,推荐使用代码中的 spl_autoload_register()__autoload() 的作用是引入没有找到的类,它接受的参数,即已知的条件是这个类的类名,所以引入的核心根据类名找到类文件所在目录,从而引入。为什么不使用 __autoload() 呢,因为 __autoload() 这个函数全局只能定义一次,如果都在里面定义类名和类文件目录的关系,这个函数将十分臃肿,因此 PHP5 开始建议使用 spl_autoload_register() 进行注册。
  2. 方框2:当访问不存在的类时,可以看到,走到了 spl_autoload_register() 函数(方框 2 输出了想要访问的类名)。因为代码中既有 spl_autoload_register(),也有 __autoload() 所以只访问了 spl_autoload_register(),只有 __autoload() 时就会访问 __autoload()
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 3

composer 支持的加载规则 psr-0 psr-4 手动map,还有什么来着

2年前 评论
  • 了解composer的自动加载
  • 从composer生成的自动加载文件看源码会了解更快

vendor/autoload.php开始看。

2年前 评论
LittleLittleBig (楼主) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!