我可以使用 PHP 8.1 函數(例如類別名稱)建立命名空間別名嗎?
我們將公司中的預設命名空間模組命名為“Subcompany”,並希望它現在成為“Company”,因為它的用途已經擴大了。
一個完美的答案是盡可能少的開銷,並且允許透明地自動加載。一個問題是 Intelephense 等工具會理解此別名。
該專案也使用 Composer,因此使用它重寫命名空間的答案也可以。
是的,並且思考:class_alias 是隨 PHP 5.3 引入的,並且它的新命名空間語言功能。它的創建是為了更容易從全域命名空間遷移到命名空間 - 實際上是在命名空間之間。
class_alias
但是,您需要先為每個舊類別/介面/特徵/枚舉註冊一個類別名稱到新的對應項。
My\Old\Lib\Name\Module\Submodule\Interface My\Tiger\Lib\Name\Module\Submodule\Interface
舊的庫已經消失,現在有了全新的 Tiger 庫。它們的所有類別等都可以透過交換命名空間前綴來映射('My\Old\Lib\Name\' -> 'My\Tiger\Lib\Name')。
'My\Old\Lib\Name\' -> 'My\Tiger\Lib\Name'
這可以在運行時完成,因為 PHP 會為您完成大部分工作。
註冊一個自動載入器,它基於舊的命名空間前綴作為新的命名空間前綴加載,並預先將類別名為舊名稱。
範例:
spl_autoload_register( static function (string $class_name) { static $old = 'My\Old\Lib\Name\'; static $new = 'My\Tiger\Lib\Name\'; // only operate on the old namespace if (0 !== strpos($class_name, $old)) { return; } $new_name = substr_replace($class_name, $new, 0, strlen($old)); class_alias($new_name, $class_name); $exists = class_exists($new_name); }, $throw = true, /* throw when registering fails */ $prepend = false /* only alias at fall-through */ );
這段程式碼很簡單,只要對註冊參數做兩點說明:
$throw = true
$prepend = false
也許值得注意的是 class_exists() 部分:
class_exists()
$exists = class_exists($new_name);
如果新類別尚未加載,它會觸發自動加載。
註冊自動載入器後,舊程式碼將自動載入舊別名下的新類別。
use My\Old\Lib\Name\Module\Boring; $boring = new Boring(); assert($boring instanceof My\Old\Lib\Name\Module\Boring); var_dump(get_class($boring)); # string(31) "My\Tiger\Lib\Name\Module\Boring"
是的,並且思考:
class_alias
是隨 PHP 5.3 引入的,並且它的新命名空間語言功能。它的創建是為了更容易從全域命名空間遷移到命名空間 - 實際上是在命名空間之間。但是,您需要先為每個舊類別/介面/特徵/枚舉註冊一個類別名稱到新的對應項。
舊的庫已經消失,現在有了全新的 Tiger 庫。它們的所有類別等都可以透過交換命名空間前綴來映射(
'My\Old\Lib\Name\' -> 'My\Tiger\Lib\Name'
)。這可以在運行時完成,因為 PHP 會為您完成大部分工作。
註冊一個自動載入器,它基於舊的命名空間前綴作為新的命名空間前綴加載,並預先將類別名為舊名稱。
範例:
這段程式碼很簡單,只要對註冊參數做兩點說明:
$throw = true
:當別名自動載入器無法註冊時,您希望立即停止應用程序,否則您會在很久以後收到奇怪的「未找到類別」錯誤。$prepend = false
:只有當仍有程式碼使用舊類別名稱時,才應呼叫回呼。因此,現在使用新命名空間和標準自動載入的標準代碼是第一位的。也許值得注意的是
class_exists()
部分:如果新類別尚未加載,它會觸發自動加載。
註冊自動載入器後,舊程式碼將自動載入舊別名下的新類別。