名稱空間和自動載入
從技術上講,自動載入通過在需要 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 檔案中。