首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 模組自動載入器實作(支援命名空間、PSR-4 風格)

     編輯:PHP 相關知識

需求

專案未使用 Composer 自動載入,需自行實作簡易模組載入器,支援:

  • 點號分隔命名空間:`Core\Database\Connection` → `modules/Core/Database/Connection.php`
  • 自訂副檔名:`.class.php`、`.inc.php`、`.php`
  • 找不到檔案拋出例外。

實作

<?php
/**
 * 簡易模組自動載入器
 * @param string $modulePath 點號分隔的模組路徑 (e.g. 'Core.Database.Connection')
 * @param string $extension 檔案副檔名 (預設 '.class.php'),支援 'inc' 簡寫
 * @return void
 * @throws RuntimeException 找不到檔案
 */
function importModule(string $modulePath, string $extension = '.class.php'): void
{
    // 正規化副檔名
    $extMap = [
        'class' => '.class.php',
        'inc'   => '.inc.php',
        'php'   => '.php',
    ];
    $ext = $extMap[$extension] ?? $extension;
    if (!str_starts_with($ext, '.')) $ext = '.' . $ext;

    // 專案模組根目錄(可從環境變數或設定取得)
    $baseDir = __DIR__ . '/modules/';

    // 轉換路徑
    $filePath = $baseDir . str_replace('.', '/', $modulePath) . $ext;
    $filePath = str_replace('//', '/', $filePath); // 防雙斜線

    if (!is_file($filePath)) {
        throw new RuntimeException("模組檔案不存在: $filePath (來源: $modulePath)");
    }

    // 載入一次
    require_once $filePath;
}

// 註冊為 SPL 自動載入器(可選)
spl_autoload_register(function(string $class) {
    try {
        // 僅處理專案命名空間
        if (str_starts_with($class, 'App\\') || str_starts_with($class, 'Modules\\')) {
            $path = __DIR__ . '/' . str_replace('\\', '/', $class) . '.php';
            if (is_file($path)) require_once $path;
        }
    } catch (Throwable) {
        // 忽略,讓後續載入器處理
    }
});

// 使用範例
importModule('Core.Database.Connection');      // 載入 modules/Core/Database/Connection.class.php
importModule('Utils.Helpers.String', 'inc');   // 載入 modules/Utils/Helpers/String.inc.php
importModule('Services.Payment.Gateway', 'php'); // 載入 modules/Services/Payment/Gateway.php

進階:PSR-4 完整實作

若需生產級自動載入,建議直接使用 Composer。若不可用,可參考 Composer ClassLoader 精簡版:

class SimplePsr4Loader
{
    private array $prefixes = []; // prefix => [baseDirs...]

    public function addNamespace(string $prefix, string|array $baseDirs, bool $prepend = false): void
    {
        $prefix = rtrim($prefix, '\\') . '\\';
        $dirs = (array)$baseDirs;
        foreach ($dirs as &$dir) $dir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
        if ($prepend) $this->prefixes[$prefix] = array_merge($dirs, $this->prefixes[$prefix] ?? []);
        else $this->prefixes[$prefix] = array_merge($this->prefixes[$prefix] ?? [], $dirs);
    }

    public function register(bool $prepend = false): void
    {
        spl_autoload_register([$this, 'loadClass'], true, $prepend);
    }

    public function loadClass(string $class): bool
    {
        foreach ($this->prefixes as $prefix => $dirs) {
            if (!str_starts_with($class, $prefix)) continue;
            $relative = substr($class, strlen($prefix));
            $file = str_replace('\\', DIRECTORY_SEPARATOR, $relative) . '.php';
            foreach ($dirs as $dir) {
                $full = $dir . $file;
                if (is_file($full)) {
                    require_once $full;
                    return true;
                }
            }
        }
        return false;
    }
}

// 使用
$loader = new SimplePsr4Loader();
$loader->addNamespace('App\\', __DIR__ . '/src');
$loader->addNamespace('Modules\\', __DIR__ . '/modules');
$loader->register();

比較

方案適用場景優點缺點
importModule()舊專案、腳本、簡易模組化零設定、直觀、可控手動呼叫、無快取、不支援自動發現
SimplePsr4Loader中型專案、無 Composer 環境標準 PSR-4、自動載入、效能尚可需手動註冊命名空間、無最佳化
Composer Autoload所有現代專案Class Map 快取、最佳化、開發/生產區分、腳本鉤子需安裝 Composer
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved