這是與命名空間有關的最后一篇,最后還是兩個比較簡單的內容,是關于命名空間和全域相關的一些類、函式、常量的使用對比,當然,最后我們還會總結一下命名空間的名稱決議規則做為這三篇系列文章的結束,
全域空間
當檔案中定義了命名空間,也就是namesapce指定了當前的命名空間后,在呼叫全域類、函式、常量時,需要添加一個“\”,也就是完全限定訪問符號來標明這個類、函式、常量是全域的那個,而不是當前命名空間中的,特別是當前命名空間中包含與全域類、函式、常量同名的內容時,
namespace FILE6;
function show()
{
echo strtoupper('aaa'), PHP_EOL; // 呼叫自己的
echo \strtoupper('aaa'), PHP_EOL; // 呼叫全域的
}
function strtoupper($str)
{
return __NAMESPACE__ . ':' . \strtoupper($str);
}
在這個FILE6命名空間中,我們定義了一個strtoupper()方法,之間說過,命名空間就是為了解決同名問題而出現的,這個方法和全域php自帶的那個方法是完全相同的名稱的,所以,在呼叫的時候我們需要呼叫的是哪個方法,那么如果當前命名空間中沒有定義這個方法呢?別急,接下來的內容就是講這個問題,
后備全域函式/常量
從上個例子中,我們就可以看出全域完全限定訪問符的作用,當沒有使用全域符時,strtoupper()方法會先呼叫當前命名空間下的方法,那么后備的作用就是如果當前命名空間中沒有找到時,會去全域找相關的函式,在檔案中的定義是這樣的:
當 PHP 遇到一個非限定的類、函式或常量名稱時,它使用不同的優先策略來決議該名稱,類名稱總是決議到當前命名空間中的名稱,因此在訪問系統內部或不包含在命名空間中的類名稱時,必須使用完全限定名稱,對于函式和常量來說,如果當前命名空間中不存在該函式或常量,PHP 會退而使用全域空間中的函式或常量,
意思也就是說,函式和常量,會有后備去全域查找的能力,但是類不行!!如果要使用全域類,一定要加全域完全限定符,我們通過一個例子來看:
namespace FILE7;
// 類必須使用完全限定的全域空間
$o1 = new \stdClass();
// $o2 = new stdClass(); // Fatal error: Uncaught Error: Class 'FILE7\stdClass' not found
// 方法會先在本命名空間查找,如果沒找到會去全域找
function strlen($str)
{
return __NAMESPACE__ . ':' . (\strlen($str) - 1);
}
echo strlen('abc'), PHP_EOL; // FILE7:2 ,當前命名空間
echo \strlen('abc'), PHP_EOL; // 3 , 全域
echo strtoupper('abc'), PHP_EOL; // ABC, 全域
// 常量也是有后備能力的
const E_ERROR = 22;
echo E_ERROR, PHP_EOL; // 22, 當前命名空間
echo \E_ERROR, PHP_EOL; // 1, 全域
echo INI_ALL, PHP_EOL; // 7, 全域
名稱決議規則
- 對完全限定名稱的函式,類和常量的呼叫在編譯時決議,例如 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() 的函式
- 嘗試查找并呼叫 全域(global) 空間中的函式 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(),
測驗代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202001/source/namespace/file6.php
[https://github.com/zhangyue0503/dev-blog/blob/master/php/202001/source/namespace/file7.php]https://github.com/zhangyue0503/dev-blog/blob/master/php/202001/source/namespace/file7.php()
參考檔案:
https://www.php.net/manual/zh/language.namespaces.global.php
https://www.php.net/manual/zh/language.namespaces.fallback.php
https://www.php.net/manual/zh/language.namespaces.rules.php
===============
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/266592.html
標籤:PHP
上一篇:php 二叉樹遍歷
