這次帶給大家php命名空間使用詳解,php命名空間使用的注意事項有哪些,下面就是實戰案例,一起來看一下。
命名空間解決的問題(手冊上也寫的很清楚,以下按照自己的理解簡化了):
1:解決程式編寫者自己寫的類別、常數、函數和php內部的或第三方的出現名稱衝突的情況。
2:建立別名,幫助解決類別、常數、函數名稱過長的情況,幫助提高程式碼的可讀性,另外名稱過長其實通常都是因為為了緩解第一類問題導致的。
1:命名空間用關鍵字namespace聲明,同時命名空間必須位於其他程式碼之前,包括任何非php程式碼以及空白符(php的declare關鍵字除外),否則會拋出一個fatal error。
例如:
<?php namespace Index; ?>
注意1:如果命名空間namespace前沒有任何程式碼及空白符,但還是出現fatal error,這個應該是由於bom頭導致的,去掉bom頭就可以了。
注意2:在命名空間下,雖然可以放置所有合法的php程式碼,但只有受命名空間影響的只有類別(抽象類別以及traits)和介面、常數和函數。
2:與目錄和檔案的關係很像,PHP 命名空間也允許指定層次化的命名空間的名稱。因此,命名空間的名字可以使用分層的方式定義,分隔符號是\。
例如:
<?php namespace Index\Col\File; define('MESSAGE','hello world'); ?>
3:一個檔案中可以定義多個命名空間,定義的語法有兩種,一種是簡單組合語法,另一種是大括號形式語法, 另外一個檔案定義多個命名空間的使用一般是多個檔案合併成一個檔案的場景,但不到萬不得已最好不要這樣,因為這樣增加了程式碼的複雜度,可讀性會降低,一般情況也沒有這種使用的必要。
簡單組合語法:
<?php namespace Index; const INSTANCE=1; namespace Col; const INSTANCE=2; ?>
大括號語法,一個檔案多個命名空間,如果還需要寫上非命名空間的程式碼,就只能用大括號語法,並且非命名空間程式碼用namespace宣告一個沒有名稱的命名空間,再用大括號即可:
<?php /*命名空间Index*/ namespace Index{ const INSTANCE=1; } /*命名空间Col*/ namespace Col{ const INSTANCE=2; } /*全局非命名空间代码*/ namespace { const INSTANCE=3; } ?>
4:多個不同的檔案可以定義同一個命名空間,也就是說同一個命名空間的內容可以分別儲存到多個不同的文件中,這裡就不舉例了。
命名空間的使用原理有三種情況,手冊上其實說的詳細但可能因為翻譯問題導致一些凌亂,這裡我簡化一下用自己的範例整理一下:
1:沒有限定名稱,也就是直接使用要讀取的類別、常數、函數、介面名稱,這種情況會讀取該內容所屬的命名空間的類別、常數、函數、介面名稱,但如果命名空間內沒有相關的數據,如果是類別和介面名稱會傳回fatal error,如果是函數和常數會自動讀取全域的函數和常數,如果全域中也沒有,才會報fatal error。
下面舉例:
<?php /*全局非命名空间代码*/ namespace { const INSTANCE=1; function test(){ echo 1; } class foo{ static function fool(){ echo 1; } } var_dump(INSTANCE); //打印出来的是1 test(); //输出1 foo::fool(); //输出1 } /*命名空间Index*/ namespace Index{ const INSTANCE=2; function test(){ echo 2; } class foo{ static function fool(){ echo 2; } } var_dump(INSTANCE); //打印出来的是2 test(); //输出2 foo::fool(); //输出2 } /*命名空间Col*/ namespace Col{ const INSTANCE=3; function test(){ echo 3; } class foo{ static function fool(){ echo 3; } } var_dump(INSTANCE); //打印出来的是3 test(); //输出2 foo::fool(); //输出2 } ?>
上面的範例每個命名空間裡輸出的都沒有限定名稱,所以會得到目前命名空間下設定的對應資料值。
如果目前命名空間沒有設置,函數和常數則會讀取全域設定的對應資料值,全域沒有對應的才會報fatal error,類別和介面都會直接報fatal error,如下面程式碼所示。
<?php /*全局非命名空间代码*/ namespace { const INSTANCE=1; function test(){ echo 1; } class foo{ static function fool(){ echo 1; } } var_dump(INSTANCE); //打印出来的是1 test(); //输出1 foo::fool(); //输出1 } /*命名空间Index*/ namespace Index{ var_dump(INSTANCE); //打印出来的是1 test(); //输出1 foo::fool(); //fatal error } ?>
2:限定名稱,分為兩種情況,一種是包含前綴的限定名稱情況,一種是包含全域限定名稱的情況。手冊上將這兩種單獨分開了,但我覺得這兩種可以合併成一起說,他們都是有限定名稱,只是前者沒有全域限定,後者有全域限定。
①包含前綴的限定名稱,這種前綴可以有多個或一個層級,但最左側不能為\全域限定詞,這種情況會讀取該程式碼所在命名空間加上該前綴限定名稱所對應數據,也就是:
所处命名空间\前缀限定\名称来读取,如果该代码是全局没有命名空间的,则直接用前缀限定名称来读取,也就是:前缀限定\名称来读取。
实例代码:
<?php /*命名空间Col\Index*/ namespace Col\Index{ const INSTANCE=1; } /*命名空间Index*/ namespace Index{ const INSTANCE=2; } /*命名空间Col*/ namespace Col{ const INSTANCE=3; var_dump(Index\INSTANCE); //打印出来的是1 读取的是Col\Index\INSTANCE } /*全局非命名空间代码*/ namespace { const INSTANCE=4; var_dump(Index\INSTANCE); //打印出来的是2 读取的是Index\INSTANCE } ?>
②全局限定前缀名称:也就是在最左侧有全局操作符\进行修饰的前缀限定名称,当然也可以没有前缀限定直接全局操作符\加上名称也是可以的。但加上全局操作符后就跟目录里的绝对路径一样,只会按照全局限定后的所设置的进行读取。
具体实例如下:
<?php /*命名空间Col\Index*/ namespace Col\Index{ const INSTANCE=1; } /*命名空间Index*/ namespace Index{ const INSTANCE=2; } /*命名空间Col*/ namespace Col{ const INSTANCE=3; var_dump(\Index\INSTANCE); //打印出来的是2 读取的是Index\INSTANCE } /*全局非命名空间代码*/ namespace { const INSTANCE=4; var_dump(\Index\INSTANCE); //打印出来的是2 读取的是Index\INSTANCE } namespace Lin{ const INSTANCE=5; var_dump(\INSTANCE); //打印出来的是4 读取的是INSTANCE,是全局非命名空间里的INSTANCE,如果没有全局操作符\,读取的会是当前命名空间的Lin\INSTANCE=5 } ?>
有时候命名空间会放在字符串中使用,如果是单引号不会通过编译器解释,所以没有任何问题,但是如果是双引号,那么就会有些意外情况了,要知道双引号里的内容是需要经过编译器进行解释然后再进行输出的,而\在编译器里的解释容易造成歧义。
例如"index\name"这里就有\n会被解释成换行,除此之外还有很多这种造成意外的情况。
因此一般我们推荐命名空间如果要放在字符串中使用,最好使用单引号,一是效率,二是安全,如果使用双引号,则必须增加一个\进行转义避免歧义,例如"index\\name"这样就没有问题了。
随手双引号的举个例子:
<?php /*全局非命名空间代码*/ namespace Index\Name{ class foo{ function construct(){ echo 2; } } } namespace{ $a= "Index\\Name\\foo"; //用\转义了\所以可以正常运行,但是如果去掉转义的话会报错Class 'Index\Nameoo',因为/f被解释成了换页符 $obj=new $a; }
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是php命名空間使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!