首頁 後端開發 php教程 什麼是命名空間?詳解PHP中的命名空間

什麼是命名空間?詳解PHP中的命名空間

Jun 14, 2017 am 11:49 AM
namespace php 命名空間

什麼是命名空間?這篇文章帶大家深入了解PHP中的命名空間(namespace),希望對大家有幫助。

什麼是命名空間?詳解PHP中的命名空間

什麼是命名空間?

從廣義來說,命名空間是一種封裝事物的方法,在許多地方都可以見到這個抽象概念。例如,在作業系統中目錄用來將相關檔案分組,而對於目錄中的檔案來說,它就扮演了命名空間的角色。

舉個簡單的例子,檔案 foo.txt 可以同時在目錄 /home/greg 和 /home/other 中存在,但在同一個目錄中不能存在兩個 foo.txt 檔案。另外,在目錄 /home/greg 外存取 foo.txt 檔案時,我們必須將目錄名稱以及目錄分隔符號放在檔案名稱之前,例如 /home/greg/foo.txt。這個原理應用在程式設計領域就是命名空間的概念。

命名空間的定義

PHP 中命名空間(namespace)是在PHP5.3 中加入的,如果你了解C++ 的話,那命名空間就不算是什麼新事物了。不過命名空間在 PHP 當中還是相當重要的。

PHP 命名空間可以解決以下兩類問題:

  • 使用者寫的程式碼與PHP 內部的類別/函數/常數或第三方類別/函數/常數之間的命名衝突;

  • 為很長的標識符名稱(通常是為了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,以提高來源代碼的可讀性。

1) 定義命名空間(使用關鍵字namespace)

雖然任意合法的PHP 程式碼都可以包含在命名空間中,但只有類別(包括抽象類別和traits)、介面、函數和常數等類型的程式碼受命名空間的影響。

命名空間的定義需要透過關鍵字namespace 來聲明,語法格式如下:

namespace 命名空间名;
登入後複製

【範例】下面我們來示範如何定義了命名空間:

<?php
    namespace MyProject;    // 定义名为 MyProject 的命名空间。
    const CONNECT_OK = 1;
    class Myclass {
        /* ... */
    }
    function Myfunc() {
        /* ... */
    }
?>
登入後複製

在聲明命名空間之前除了用於定義原始檔案編碼方式的declare 語句外,所有非PHP 程式碼(包括空白符號)都不能出現在命名空間聲明之前。

另外,與 PHP 其它的語言特徵不同,同一個命名空間可以定義在多個檔案中,即允許將同一個命名空間的內容分割存放在不同的檔案中。

2) 定義子命名空間

與目錄和檔案的關係很像,PHP 中的命名空間也允許指定層次化的命名空間名稱。因此,命名空間的名字可以使用分層的方式定義:

namespace App\Model;
namespace App\Controller\Home;
登入後複製

【範例】定義一個子命名空間:

<?php
    namespace MyProject\Controller\Home;    // 定义名为 MyProject 的命名空间。
    const CONNECT_OK = 1;
    class Myclass {
        /* ... */
    }
    function Myfunc() {
        /* ... */
    }
?>
登入後複製

3) 在同一個檔案中定義多個命名空間

在一個檔案中也可以定義多個命名空間,在同一檔案中定義多個命名空間有兩種語法形式,下面透過範例示範:

# 【範例】定義多個命名空間-簡單組合語法。

<?php
    namespace MyProject;
    const CONNECT_OK = 1;
    class className {
        /* ... */
    }
    namespace AnotherProject;
    const CONNECT_OK = 1;
    class className {
        /* ... */
    }
?>
登入後複製

【範例】定義多個命名空間-大括號{ }語法。

<?php
    namespace MyProject{
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
    namespace AnotherProject{
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
?>
登入後複製

在實際的程式設計實踐中,並不提倡在同一個檔案中定義多個命名空間。定義多個命名空間主要用於將多個 PHP 腳本合併在同一個檔案中。在定義多個命名空間時建議使用大括號形式的語法。

將全域的非命名空間中的程式碼與命名空間中的程式碼組合在一起,只能使用大括號形式的語法,同時全域程式碼必須用一個不帶名稱的namespace 語句加上大括號括起來,如下所示:

<?php
    namespace MyProject{        // 命名空间中的代码
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
    namespace {                 // 命名空间外的全局代码
        $obj = new MyProject\className();
    }
?>
登入後複製

使用命名空間:基礎

在討論如何使用命名空間之前,必須了解PHP 是如何知道要使用哪一個命名空間中的元素的。我們可以將 PHP 命名空間與檔案系統作一個簡單的類比。在檔案系統中存取一個檔案有三種方式:

  • 相對檔案名稱形式如 foo.txt。它會被解析為 currentdirectory/foo.txt,其中 currentdirectory 表示目前目錄。因此如果目前目錄是 /home/foo,則該檔案名稱被解析為 /home/foo/foo.txt;

  • 相對路徑名稱形式如 subdirectory/foo.txt。它會被解析為 currentdirectory/subdirectory/foo.txt;

  • #絕對路徑名稱形式如 /main/foo.txt。它會被解析為 /main/foo.txt。

PHP 命名空間中的元素使用相同的原理。例如,命名空間下的類別名稱可以透過三種方式引用:

  • 非限定名稱,或不包含前綴的類別名稱,例如$a=new foo() ;foo::staticmethod();。如果目前命名空間是 currentnamespace,那麼 foo 將會解析為 currentnamespace\foo。如果使用 foo 的程式碼是全域的,不包含在任何命名空間中的程式碼,則 foo 會被解析為 foo。

  • 限定名称,或包含前缀的名称,例如$a = new subnamespace\foo();subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为 subnamespace\foo。

  • 完全限定名称,或包含了全局前缀操作符的名称,例如$a = new \currentnamespace\foo();\currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名 currentnamespace\foo。

警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。

下面是一个使用这三种方式的实例,我们需要两个 PHP 源文件,分别是 demo.php 和 index.php,示例代码如下:

1) demo.php

<?php
    namespace Foo\Bar\Demo;
    const FOO = 1;
    function foo() {}
    class foo
    {
        public function demo() {
            echo &#39;命名空间为:Foo\Bar\Demo&#39;;
        }
    }
?>
登入後複製

2) index.php

<?php
    namespace Foo\Bar;
    include &#39;Demo.php&#39;;
    const FOO = 2;
    function foo() {
        echo &#39;Foo\Bar 命名空间下的 foo 函数<br>&#39;;
    }
    class foo
    {
        static function demo(){
            echo &#39;命名空间为:Foo\Bar<br>&#39;;
        }
    }
    /* 非限定名称 */
    foo();                  // 解析为 Foo\Bar\foo resolves to function Foo\Bar\foo
    foo::demo();            // 解析为类 Foo\Bar\foo 的静态方法 staticmethod。
    echo FOO.&#39;<br>&#39;;        // 解析为常量 Foo\Bar\FOO
    /* 限定名称 */
    Demo\foo();             // 解析为函数 Foo\Bar\Demo\foo
    Demo\foo::demo();       // 解析为类 Foo\Bar\Demo\foo,
                            // 以及类的方法 demo
    echo Demo\FOO.&#39;<br>&#39;;   // 解析为常量 Foo\Bar\Demo\FOO
                                     
    /* 完全限定名称 */
    \Foo\Bar\foo();         // 解析为函数 Foo\Bar\foo
    \Foo\Bar\foo::demo();   // 解析为类 Foo\Bar\foo, 以及类的方法 demo
    echo \Foo\Bar\FOO.&#39;<br>&#39;; // 解析为常量 Foo\Bar\FOO
?>
登入後複製

运行结果如下:

Foo\Bar 命名空间下的 foo 函数
命名空间为:Foo\Bar
2
Foo\Bar\Demo 命名空间下的 foo 函数
命名空间为:Foo\Bar\Demo
1
Foo\Bar 命名空间下的 foo 函数
命名空间为:Foo\Bar
2
登入後複製

注意:访问任意全局类、函数或常量,都可以使用完全限定名称,例如 \strlen() 或 \Exception 等。

使用命名空间:别名/导入

PHP 允许通过别名引用或导入的方式来使用外部的命名空间,这是命名空间的一个重要特征。这有点类似于在类 unix 文件系统中可以创建对其它的文件或目录的符号连接。

使用 use 关键字可以实现命名空间的导入,从 PHP5.6 开始允许导入函数和常量,并为它们设置别名。语法格式如下:

use namespace;
登入後複製

在 PHP 中,别名是通过操作符 use 与 as 来实现的,语法格式如下:

use 命名空间 as 别名;
登入後複製

【示例】使用 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 还支持在一行中导入多个命名空间,中间使用,隔开,示例代码如下:

<?php
    use My\Full\Classname as Another, My\Full\NSname;
    $obj = new Another;     // 实例化 My\Full\Classname 对象
    NSname\subns\func();    // 调用 My\Full\NSname\subns\func 函数
?>
登入後複製

导入操作是编译执行的,但动态的类名称、函数名称或常量名称则不是。

<?php
    use My\Full\Classname as Another, My\Full\NSname;
    $obj = new Another; // 实例化一个 My\Full\Classname 对象
    $a = &#39;Another&#39;;
    $obj = new $a;      // 实际化一个 Another 对象
?>
登入後複製

另外,导入操作只影响非限定名称和限定名称。完全限定名称由于是确定的,故不受导入的影响。

namespace 关键字和 __NAMESPACE__ 常量

PHP 支持两种抽象的访问当前命名空间内部元素的方法,__NAMESPACE__ 魔术常量和 namespace 关键字。

__NAMESPACE__ 常量的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它是一个空的字符串。示例代码如下:

<?php
    namespace App\Controller\Home;
    echo __NAMESPACE__;
?>
登入後複製

运行结果如下:

App\Controller\Home
登入後複製

namespace 关键字可用来显式访问当前命名空间或子命名空间中的元素,它等价于类中的 self 操作符。示例代码如下:

<?php
    namespace MyProject;
    use Foo\Bar\Demo as demo;       // 导入 Foo\Bar\Demo 命名空间
    blah\mine();                    // 调用 MyProject\blah\mine() 函数
    namespace\blah\mine();          // 调用 MyProject\blah\mine() 函数
    namespace\func();               // 调用 MyProject\func() 函数
    namespace\sub\func();           // 调用 MyProject\sub\func() 函数
    namespace\cname::method();      // 调用 MyProject\cname 类的静态方法 method
    $a = new namespace\sub\cname(); // 实例化 MyProject\sub\cname 对象
    $b = namespace\CONSTANT;        // 将常量 MyProject\CONSTANT 的值赋给 $b
?>
登入後複製

命名空间名称解析规则

在说明名称解析规则之前,我们先来看看命名空间名称的定义:

  • 非限定名称:名称中不包含命名空间分隔符的标识符,例如 Foo;

  • 限定名称:名称中含有命名空间分隔符的标识符,例如 Foo\Bar;

  • 完全限定名称:名称中包含命名空间分隔符,并以命名空间分隔符开始的标识符,例如 \Foo\Bar。namespace\Foo 也是一个完全限定名称。

名称解析遵循下列规则:

  • 對完全限定名稱的函數,類別和常數的呼叫在編譯時解析。例如 new \A\B 解析為類別 A\B;
  • 所有的非限定名稱和限定名稱(非完全限定名稱)根據目前的導入規則在編譯時進行轉換。例如,如果命名空間A\B\C 被導入為C,那麼對C\D\e() 的呼叫就會被轉換為A\B\C\D\e();
  • 在命名空間內部,所有的沒有根據導入規則轉換的限定名稱均會在其前面加上目前的命名空間名稱。例如,在命名空間A\B 內部呼叫C\D\e(),則C\D\e() 會轉換為A\B\C\D\e();
  • 非限定類別名稱根據目前的導入規則在編譯時轉換(以全名取代短的導入名稱)。例如,如果命名空間A\B\C 導入為C,則new C() 轉換為new A\B\C();
  • 在命名空間內部(例如A\B),對非限定名稱的函數呼叫是在執行時間解析的。例如對函數foo() 的呼叫是這樣解析的:
    • 在目前命名空間中尋找名為A\B\foo() 的函數;

    • 嘗試尋找並呼叫全域空間中的foo() 函數。

  • 在命名空間(例如 A\B)內部對非限定名稱或限定名稱類別(非完全限定名稱)的呼叫是在執行時間解析的。以下是呼叫new C() 及new D\E() 的解析過程:
    • new C() 的解析:

      • 在目前命名空間中尋找A \B\C 類別;
      • 嘗試自動裝載類別A\B\C。
    • new D\E() 的解析:

      • #在類別名稱前面加上目前命名空間名稱變成:A\B\ D\E,然後尋找該類別;
      • 嘗試自動裝載類別A\B\D\E。
    • 為了引用全域命名空間中的全域類,必須使用完全限定名稱 new \C()。

推薦學習:《PHP影片教學

以上是什麼是命名空間?詳解PHP中的命名空間的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles