PHP 核心特性之名稱空間

2020-07-16 10:06:09
提出

在名稱空間提出之前,不同的元件很容易碰到命名的衝突,例如 Request 、Response 等常見的命名。PHP 在 5.3 後提出了名稱空間用來解決元件之間的命名衝突問題,主要參考了檔案系統的設計:

同一個目錄下不允許有相同的檔名 - 同一個名稱空間下不允許有相同的類;

不同的目錄可以有同名檔案 - 不同的名稱空間可以有相同的類;

定義

使用 namespace 關鍵字來定義一個名稱空間。其中,頂層名稱空間通常為廠商名,不同開發者的廠商名稱空間是唯一的。名稱空間不需要與檔案目錄一一對應,但是最好遵守 PSR-4 規範。

<?php
namespace SymfonyComponentHttpFoundation;
class Request {
}

名稱空間必須在所有程式碼之前宣告,唯一的例外就是 declare 關鍵字。

<?php
declare(strict_types=1);
namespace App;

名稱空間內可包含任意 PHP 程式碼,但是僅對類 (包括抽象類和 Trait)、介面、函數和常數這四種型別生效。

<?php
namespace MyProject;
const CONNECT_OK = 1;
class FOO {}
interface Foo{}
function foo() {}

使用

使用 use 關鍵字來引入名稱空間

<?php
namespace App;
use SymfonyComponentHttpFoundationRequest;
use FooBar;
class Test {
    public function run() 
    {
        $bar = new Bar();
    }
}

定義和使用推薦遵循 PSR-2 的規範

namespace 之後必須存在一個空行;

所有 use 宣告必須位於 namespace 宣告之後;

每條 use 宣告必須只有一個 use 關鍵字。

use 語句塊之後必須存在一個空行。

當 use 引入的類出現同名時,可使用 as 來定義別名

<?php
namespace App;
use FooBar as BaseBar;
class Bar extends BaseBar {
}

限定符

除了使用 use 外,還可以直接使用 限定符來進行解析,規則很簡單:如果含有 字首則代表從全域性名稱空間開始解析,否則則代表從當前名稱空間開始解析。

<?php
namespace App;
FooBarfoo();  // 解析成 FooBarfoo();
FooBarfoo();  // 解析成 AppFooBarfoo();

此規則也適用於函數、常數等

$a = strlen('hi'); // 呼叫全域性函數 strlen
$b = INI_ALL; // 存取全域性常數 INI_ALL
$c = new Exception('error'); // 範例化全域性類 Exception

有兩個需要特別注意的地方:

對於函數和常數而言,如果當前名稱空間不存在,則會自動去全域性名稱空間去尋找,因此可省略 字首。對於類而言,如果當前名稱空間解析不到,不會去全域性空間尋找,因此,不可省略

$a = strlen('hi');
$b = INI_ALL;
$c = new Exception('error'); // 錯誤
$c = new Exception('error'); // 正確

當動態呼叫名稱空間時,該名稱空間始終會被當成是全域性名稱空間,因此可以省略字首

$class1 = 'FooBar';
$object1 = new $class1;  // 始終被解析成 FooBar

在內部存取名稱空間

PHP 支援兩種抽象的存取當前名稱空間內部元素的方法,__NAMESPACE__ 魔術常數和 namespace 關鍵字。

__NAMESPACE__ 常數的值是包含當前名稱空間名稱的字串,如果是在全域性名稱空間,則返回空字串。

<?php
namespace MyProject;
function get($classname)
{
    $a = __NAMESPACE__ . '' . $classname;
    return new $a;
}

關鍵字 namespace 可用來顯式存取當前名稱空間或子名稱空間中的元素。它等價於類中的 self 操作符

namespace App;
use blahblah as mine; 
blahmine(); // Appblahmine()
namespaceblahmine(); // Appblahmine()
namespacefunc(); // Appfunc()
namespacesubfunc(); // Appsubfunc()
namespacecname::method(); // Appcname::method()
$a = new namespacesubcname(); // Appsubcname
$b = namespaceCONSTANT; // AppCONSTANT

跳脫 符號

此外,推薦對所有的 進行跳脫,避免出現不可預期的後果

$class = "dangerousname"; // n 被解析成換行符
$obj = new $class;
$class = 'dangerousname'; // 正確,但是不推薦
$class = 'dangerousname'; // 推薦
$class = "dangerousname"; // 推薦

以上就是PHP 核心特性之名稱空間的詳細內容,更多請關注TW511.COM其它相關文章!