關鍵字「use」已被用於三個不同的應用:
1- 在命名空間中導入/別名類別、特性、常數等,
2- 在類別中插入特性,
3- 在閉包中繼承變數。
此頁面僅關於第一個應用:導入/別名。特性可以插入到類別中,但這與在命名空間中導入特性不同,如範例 5 所述,這不能在區塊範圍內完成。這可能會造成混淆,尤其是在搜尋關鍵字「use」的所有結果都導向此處關於導入/別名的說明文件時。
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
使用別名或匯入來參考外部完整限定名稱的能力是命名空間的一項重要功能。這類似於基於 Unix 的檔案系統建立檔案或目錄的符號連結的能力。
PHP 可以為常數、函式、類別、介面、特性 (Traits)、列舉 (Enums) 和命名空間建立別名(/匯入)。
別名是使用 use
運算子來完成的。以下範例顯示了所有 5 種匯入方式
範例 #1 使用 use 運算子匯入/建立別名
<?php
namespace foo;
use My\Full\Classname as Another;
// 這與 use My\Full\NSname as NSname 相同
use My\Full\NSname;
// 導入全域類別
use ArrayObject;
// 導入函式
use function My\Full\functionName;
// 函式別名
use function My\Full\functionName as func;
// 導入常數
use const My\Full\CONSTANT;
$obj = new namespace\Another; // 建立 foo\Another 類別的物件
$obj = new Another; // 建立 My\Full\Classname 類別的物件
NSname\subns\func(); // 呼叫 My\Full\NSname\subns\func 函式
$a = new ArrayObject(array(1)); // 建立 ArrayObject 類別的物件
// 如果沒有 "use ArrayObject",則會建立 foo\ArrayObject 類別的物件
func(); // 呼叫 My\Full\functionName 函式
echo CONSTANT; // 顯示 My\Full\CONSTANT 的值
?>
Foo\Bar
,而不是不包含命名空間分隔符號的全域名稱,例如 FooBar
),開頭的反斜線是不必要的,也不建議使用,因為導入名稱必須是完整限定的,並且不會相對於目前的命名空間進行處理。
PHP 還支援一個便捷的捷徑,可以將多個 use 陳述式放在同一行。
範例 #2 使用 use 運算子導入/設定別名,多個 use 陳述式合併
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 建立 My\Full\Classname 類別的物件
NSname\subns\func(); // 呼叫 My\Full\NSname\subns\func 函式
?>
導入是在編譯時執行的,因此不會影響動態的類別、函式或常數名稱。
範例 #3 導入和動態名稱
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 建立 My\Full\Classname 類別的物件
$a = 'Another';
$obj = new $a; // 建立 Another 類別的物件
?>
此外,導入只影響非限定名稱和限定名稱。完全限定名稱是絕對的,不受導入影響。
範例 #4 導入和完全限定名稱
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 建立 My\Full\Classname 類別的物件
$obj = new \Another; // 建立 Another 類別的物件
$obj = new Another\thing; // 建立 My\Full\Classname\thing 類別的物件
$obj = new \Another\thing; // 建立 Another\thing 類別的物件
?>
use
關鍵字必須在檔案的最外層作用域(全域作用域)或命名空間宣告內部宣告。這是因為導入是在編譯時完成的,而不是執行時,所以它不能是區塊作用域。以下範例將顯示 use
關鍵字的非法用法
範例 #5 非法導入規則
<?php
namespace Languages;
function toGreenlandic()
{
use Languages\Danish;
// ...
}
?>
注意事項:
導入規則是基於每個檔案的,這意味著被引入的檔案將*不會*繼承父檔案的導入規則。
use
宣告從同一個 命名空間
導入的類別、函式和常數可以在單個 use
陳述式中組合在一起。
<?php
使用 some\namespace\ClassA;
使用 some\namespace\ClassB;
使用 some\namespace\ClassC 作為 C;
使用函式 some\namespace\fn_a;
使用函式 some\namespace\fn_b;
使用函式 some\namespace\fn_c;
使用常數 some\namespace\ConstA;
使用常數 some\namespace\ConstB;
使用常數 some\namespace\ConstC;
// 等同於以下的群組使用宣告
使用 some\namespace\{ClassA, ClassB, ClassC 作為 C};
使用函式 some\namespace\{fn_a, fn_b, fn_c};
使用常數 some\namespace\{ConstA, ConstB, ConstC};
關鍵字「use」已被用於三個不同的應用:
1- 在命名空間中導入/別名類別、特性、常數等,
2- 在類別中插入特性,
3- 在閉包中繼承變數。
此頁面僅關於第一個應用:導入/別名。特性可以插入到類別中,但這與在命名空間中導入特性不同,如範例 5 所述,這不能在區塊範圍內完成。這可能會造成混淆,尤其是在搜尋關鍵字「use」的所有結果都導向此處關於導入/別名的說明文件時。
這裡提供一個方便的方法,可以使用單個 use 關鍵字導入類別、函式和常數。
<?php
use Mizo\Web\ {
Php\WebSite,
Php\KeyWord,
Php\UnicodePrint,
JS\JavaScript,
function JS\printTotal,
function JS\printList,
const JS\BUAIKUM,
const JS\MAUTAM
};
?>
我找不到這個問題的答案,所以我自行測試了一下。
我認為這點值得注意
<?php
use ExistingNamespace\NonExsistingClass;
use ExistingNamespace\NonExsistingClass as whatever;
use NonExistingNamespace\NonExsistingClass;
use NonExistingNamespace\NonExsistingClass as whatever;
?>
以上程式碼都不會造成錯誤,除非您真的嘗試使用您導入的類別。
<?php
// 而這段程式碼會因為不存在的類別而產生標準的 PHP 錯誤。
use ExistingNamespace\NonExsistingClass as whatever;
$whatever = new whatever();
?>
請注意,程式碼 `use ns1\c1` 可以指從命名空間 `ns1` 導入類別 `c1`,也可以指導入整個命名空間 `ns1\c1`,甚至可以在同一行中同時導入兩者。範例:
<?php
namespace ns1;
class c1{}
namespace ns1\c1;
class c11{}
namespace main;
use ns1\c1;
$c1 = new c1();
$c11 = new c1\c11();
var_dump($c1); // object(ns1\c1)#1 (0) { }
var_dump($c11); // object(ns1\c1\c11)#2 (0) { }
如果您在 CLI 測試程式碼,請注意命名空間別名無法運作!
(在我繼續之前,此範例中的所有反斜線都已更改為百分號,因為我無法在貼文預覽中顯示合理的結果。請在接下來的內容中將所有百分號理解為反斜線。)
假設您有一個要在 myclass.php 中測試的類別
<?php
namespace my%space;
class myclass {
// ...
}
?>
接著您進入 CLI 進行測試。您可能會認為這樣應該可行,因為您是一行一行輸入的
require 'myclass.php';
use my%space%myclass; // 應該將 'myclass' 設定為 'my%space%myclass' 的別名
$x = new myclass; // 致命錯誤
我認為這是因為別名只在編譯時期解析,而 CLI 只是單純地評估敘述;因此 use 敘述在 CLI 中無效。
如果您將測試程式碼放入 test.php
<?php
require 'myclass.php';
use my%space%myclass;
$x = new myclass;
//...
?>
它會正常運作。
我希望這樣可以減少未老先禿的人數。
您可以多次「使用」相同的資源,只要每次使用時都以不同的別名導入即可。
例如
<?php
use Lend;
use Lend\l1;
use Lend\l1 as l3;
use Lend\l2;
use Lend\l1\Keller;
use Lend\l1\Keller as Stellar;
use Lend\l1\Keller as Zellar;
use Lend\l2\Keller as Dellar;
...
?>
在上面的例子中,「Keller」、「Stellar」和「Zellar」都是「\Lend\l1\Keller」的參考,如同「Lend\l1\Keller」、「l1\Keller」和「l3\Keller」。
有一點並非顯而易見,尤其是在 PHP 5.3 中,那就是導入語句中的命名空間解析並非遞迴解析。也就是說:如果您為一個導入設定別名,然後在另一個導入中使用該別名,則後者的導入將不會以前者的導入完全解析。
例如
use \Controllers as C;
use C\First;
use C\Last;
First 和 Last 命名空間都不會如預期般解析為 \Controllers\First 或 \Controllers\Last。
請注意,「use」導入/別名只適用於目前的命名空間區塊。
<?php
namespace SuperCoolLibrary
{
class Meta
{
static public function getVersion()
{
return '2.7.1';
}
}
}
namespace
{
use SuperCoolLibrary\Meta;
echo Meta::getVersion();//輸出 2.7.1
}
namespace
{
echo Meta::getVersion();//致命錯誤
}
?>
要獲得預期的行為,您應該使用
class_alias('SuperCoolLibrary\Meta','Meta');
中文翻譯有誤
// 如果不使用 "use \ArrayObject" ,則實例化一個 foo\ArrayObject 對象
應該改成
// 如果不使用 "use ArrayObject" ,則實例化一個 foo\ArrayObject 對象
/*********************************************/
中文說明翻譯有錯誤
// 如果不使用 "use \ArrayObject" ,則實例化一個 foo\ArrayObject 對象
這句話應該修正為
// 如果不使用 "use ArrayObject" ,則實例化一個 foo\ArrayObject 對象
請記住,命名空間的別名設定是完全可行的,例如:
<?php
use A\B\C\D\E\User;
new User();
?>
也可以寫成
<?php
use A\B\C\D\E as ENamespace;
new ENamespace\User();
?>
然而,以下寫法將無法運作
<?php
use A\B\C\D\E as ENamespace;
use ENamespace\User;
new User();
?>
> PHP 錯誤:找不到類別 "ENamespace\User"
因為引入動作發生在編譯時期,所以在條件式中嵌入 use 關鍵字無法實現多型。
例如:
<?php
if ($objType == 'canine') {
use Animal\Canine as Beast;
}
if ($objType == 'bovine') {
use Animal\Bovine as Beast;
}
$oBeast = new Beast;
$oBeast->feed();
?>
為了釐清在類別中插入 Trait 和在命名空間中引入 Trait 的區別,以下範例先引入 Trait,然後再插入 Trait。
<?php
namespace ns1;
trait T {
static $a = "In T";
}
namespace ns2;
use ns1\T; // 在命名空間 ns2 中引入 Trait ns1\T 的名稱
class C {
use T; // 在類別 C 中插入 Trait T,使用已引入的名稱。
}
namespace main;
use ns2\C;
echo C::$a; // In T;
注意:您可以引入不存在的項目而不會產生錯誤
<?php
use UndefinedClass;
use function undefined_fn;
use const UNDEFINED_CONST;
?>
但你無法使用/呼叫它們
<?php
$new UndefinedClass; // 錯誤:使用了未定義的類別
use function undefined_fn; // 錯誤:使用了未定義的函式
use const UNDEFINED_CONST; // 錯誤:使用了未定義的常數
?>