名稱空間和自動載入

從技術上講,自動載入通過在需要 PHP 類但未找到時執行回撥來工作。這種回撥通常會嘗試載入這些類。

通常,自動載入可以理解為在需要類時根據類的完全限定名稱(FQN)從適當的路徑載入 PHP 檔案(特別是 PHP 類檔案,其中 PHP 原始檔專用於特定類)的嘗試。

假設我們有這些類:

application\controllers\Base 的類檔案:

<?php
namespace application\controllers { class Base {...} }

application\controllers\Control 的類檔案:

<?php
namespace application\controllers { class Control {...} }

application\models\Page 的類檔案:

<?php
namespace application\models { class Page {...} }

在原始檔夾下,這些類應分別作為其 FQN 放在路徑中:

  • 原始檔夾
    • applications
      • controllers
        • Base.php
        • Control.php
      • models
        • Page.php

使用此函式,此方法可以根據 FQN 以程式設計方式解析類檔案路徑:

function getClassPath(string $sourceFolder, string $className, string $extension = ".php") {
    return $sourceFolder . "/" . str_replace("\\", "/", $className) . $extension; // note that "/" works as a directory separator even on Windows
}

spl_autoload_register 函式允許我們在需要時使用使用者定義的函式載入類:

const SOURCE_FOLDER = __DIR__ . "/src";
spl_autoload_register(function (string $className) {
    $file = getClassPath(SOURCE_FOLDER, $className);
    if (is_readable($file)) require_once $file;
});

此函式可以進一步擴充套件為使用後臺載入方法:

const SOURCE_FOLDERS = [__DIR__ . "/src", "/root/src"]);
spl_autoload_register(function (string $className) {
    foreach(SOURCE_FOLDERS as $folder) {
        $extensions = [
            // do we have src/Foo/Bar.php5_int64?
            ".php" . PHP_MAJOR_VERSION . "_int" . (PHP_INT_SIZE * 8),
            // do we have src/Foo/Bar.php7?
            ".php" . PHP_MAJOR_VERSION,
            // do we have src/Foo/Bar.php_int64?
            ".php" . "_int" . (PHP_INT_SIZE * 8),
            // do we have src/Foo/Bar.phps?
            ".phps"
            // do we have src/Foo/Bar.php?
            ".php"
        ];
        foreach($extensions as $ext) {
            $path = getClassPath($folder, $className, $extension);
            if(is_readable($path)) return $path;
        }
    }
});

請注意,只要載入使用此類的檔案,PHP 就不會嘗試載入類。它可以在指令碼中間載入,甚至可以在關閉函式中載入。這是開發人員(尤其是使用自動載入的開發人員)應該避免在執行時替換執行原始檔的原因之一,尤其是在 phar 檔案中。