PHP 关於 autoload

Autoload

PHP 可以透过 include、include_once、require、require_once 来将档案引入, 一般来说以 OOP 写法习惯, 一个档案一个 class, 所以如果我们要用到 Car.php 的 Car class, 我们必须引入 Car.php

// index.php
include "Car.php";

$car = new Car();

这样没有问题, 但是如果我们有很多 class 要用时, 都要一个一个手动引入, 实在是有违工程师初心, 最好是用到的时候表面上可以直接用, 实际上系统帮我们自动引入相关 php 档案, PHP 提供了一些 spl_autoload 相关函数来让我们可以完成自动引入的功能

<?php
/*
spl_autoload_register(?callable $callback = null, bool $throw = true, bool $prepend = false): bool
注册一个函数到 spl_autoload 伫列, 如果伫列还没启用就启用
$callback: 欲注册的自动引入函数, 如果没有提供, 会自动注册 spl_autoload 函数, 这是系统预设的自动引入函数
$throw: 无法注册成功时, 是否抛出异常
$prepend: 若为 true, 表示注册的函数放入伫列头部, false, 放入尾部
概念: 当使用到未被定义的 class 或 interface 时, PHP 引擎会通过自动引入函数来引入所需要的 class, interface 
*/
// 假设 class 都放在 ./classes 目录里
// ./classes/Car.php
class Car
{
  public function start()
  {
    echo "car is starting";
  }
}

// index.php
function autoload($className)  $filename;
{
  $filename = __DIR__ . "/classes/" . $className . ".php";
  if (is_readable($filename)) {
    include $filename;
  } 
}

spl_autoload_register("autoload");
$car = new Car();
$car->start();

再搭配 namesapce 的使用可以, 实作出 PSR-4 的 Autoloader

<?php
// 自动引入类
class Psr4AutoLoad
{
    // 这里面存放命名空间映射
    protected $maps = [];
    public function __construct()
    {
        spl_autoload_register([$this, 'autoload']);
    }

    // 自己写的自动引入
    public function autoload($className)
    {
        // 完整的类名由命名空间名和类名组成
        // 得到命名空间名, 根据命名空间名得到其目录路径
        $pos = strrpos($className, '\\'); //找最右边的'\'
        $namespace = substr($className, 0, $pos);
        // 得到类名
        $realClass = substr($className, $pos + 1);
        // 找到文件并且包含进来
        $this->mapLoad($namespace, $realClass);

    }

    // 根据命名空间名得到目录路径并且拼接真正的文件全路径
    protected function mapLoad($namespace, $realClass)
    {
        if (array_key_exists($namespace, $this->maps)) {
            $namespace = $this->maps[$namespace];
        }

        // 处理路径
        $namespace = rtrim(str_replace('\\/', '/', $namespace), '/') . '/';
        // 拼接文件全路径
        $filePath = $namespace . $realClass . '.php';
        // 将该文件包含进来即可
        if (file_exists($filePath)) {
            include $filePath;
        } else {
            die('该文件不存在');
        }

    }

    // 给一个命名空间, 给一个路径, 将命名空间和路径保存到映射阵列中
    public function addMaps($namespace, $path)
    {
        if (array_key_exists($namespace, $this->maps)) {
            die('此命名空间已经映射过');
        }
        // 命名空间和路径以键值对形式存放到阵列中
        $this->maps[$namespace] = $path;
    }
}
$autoloader = new Psr4AutoLoad();

<<:  [Part 1 ] Vue.js 的精随-元件

>>:  DAY02 - 环境安装

[Day10] 设定 Actions On Google 专案

接续昨日的对话流设计, 现在我们要进入实作的部分让各位能更了解设计流程。 首先从设定 Action...

Day3 自订电脑开机讯息

上一回,我提到 CC: Tweaked 的 Computer 方块有许多基础指令 但我不打算逐一介绍...

Wentz的风险模型

Wentz的风险模型 (Wentz’s Risk Model)结合了孔雀模型(Peacock Mo...

Day17【Web】网路攻击:点击劫持 Clickjacking

点击劫持 点击劫持(Clickjacking) 技术又称为 界面伪装攻击(UI redress at...

DAY29-VSCODE安装

直接在官网上下载即可。 这边选择自己的系统 这里将这两个打勾就能直接用右键开启 ...