命名空間一個最明確的目的是解決重名問題,PHP中不允許兩個函數或類別出現相同的名字,否則會產生一個致命的錯誤。這種情況只要避免命名重複就可以解決,最常見的做法就是約定一個前綴。
範例:專案中有兩個模組:article和message board,它們各自有一個處理使用者留言的類別Comment。之後我可能想要增加對所有用戶留言的一些資訊統計功能,比如說我想得到所有留言的數量。這時候呼叫它們Comment提供的方法是很好的做法,但是同時引入各自的Comment類別顯然是不行的,程式碼會出錯,在另一個地方重寫任何一個Comment也會降低維護性。那這時只能重構類別名,我約定了一個命名規則,在類別名稱前面加上模組名,像這樣:Article_Comment、MessageBoard_Comment
可以看到,名字變得很長,那意味著以後使用Comment的時候會寫更多的程式碼(至少字元多了)。並且,以後如果要對各個模組增加更多的一些整合功能,或者是互相調用,發生重名的時候就需要重構名字。當然在專案開始的時候就注意到這個問題,並規定命名規則就能很好的避免這個問題。另一個解決方法可以考慮使用命名空間。
在宣告一個命名空間時,花括弧內不僅可以包含變量,而且還可以包含以下類型:
變數(可以帶有初始化)
常數
函數(可以是定義或宣告)
結構體
類別
模板
#命名空間(命名空間可以嵌套定義)
命名空間的使用概要:
Tips:在以下範例中成為了兩個文件,一個Demo. php,一個index.php,兩個檔案處於同級目錄下;Demo.php檔案中書寫命名空間以及Demo類,index.php呼叫Demo.php中的Demo類別;如下範例中的「輸出結果」即表示瀏覽器存取index.php。
簡單的範例
Demo.php檔案程式碼
<?php namespace DemoNameSpace; class Demo { private $mysqlHandle; public function construct(){ echo 'This is namespace of PHP demo ,The Demo magic constant "NAMESPACE" is '.NAMESPACE; }}?>
index.php檔案程式碼
<?php include 'Demo.php'; use DemoNameSpace\Demo; $DemoObj = new Demo(); ?>
輸出結果1:“ This is namespace of PHP demo ,The Demo magic constant "NAMESPACE" is DemoNameSpace」
以上範例的說明:Demo.php中有一個_NAMESPACE魔法常數;「它包含目前命名空間名稱的字串。在全域的,不包括在任何命名空間中的程式碼,它包含一個空的字串。文件,如下:
<?php include 'Demo.php'; $Demo = new Demo(); ?>
輸出結果2:「Fatal error: Class 'Demo' not found in F:\JJserver\demo\index.php on line 4」
這個是常見的「致命錯誤」訊息了。依照常規的php程式思路,這裡的輸出應該是跟「輸出結果1」一致的,但這裡它偏要來個致命錯誤,這下要抓狂了吧? ~
行,先把抓狂的麻煩解決,去掉(或註解掉)Demo.php檔案中的:「namespace DemoNameSpace;」這個語句,就正常了。這是咱們平常寫class、呼叫class最常見的書寫方法,就不再解釋這種不使用namespace的情況了。
比較使用namespace與不使用namespace的兩種輸出情況,並加入namespace的定義理解後,上述出現致命錯誤的情況就很好理解了。在Demo.php中定義了一個namespace,也就是命名空間後,接著定義了Demo類,然後這個Demo類別就被歸併到了DemoNameSpace命名空間中去了,那麼要呼叫這個Demo類時,自然要先呼叫這個DemoNameSpace命名空間了,也就是在index.php檔案中使用「useDemoNameSpace\Demo」語句了。
二、複雜一點的範例
Demo.php檔案程式碼
<?php namespace DemoNameSpace; class Demo { private $mysqlHandle; public function construct(){ echo 'This is namespace of PHP demo ,The Demo magic constant "NAMESPACE" is '.NAMESPACE; }} namespace DemoNameSpace1; const constDefine = 'JJonline1'; class Demo { private $mysql; const constDefine = 'JJonline2'; public function construct() { echo 'The const constant outside class is: '.constDefine; echo '===cut-off rule of god!!!!==='; echo 'The const constant inside class is: '.self::constDefine; }}?>
index.php檔案程式碼
<?php include 'Demo.php'; use DemoNameSpace1\Demo as Test; $Demo = new Test(); echo '||||'.DemoNameSpace1\constDefine;?>
輸出結果3:「The const constant outside class is: JJonline1===cut-off rule of god!!!!===The const constant inside class is: JJonline2||||JJonline1”
这个结果在没有命名空间的时候,就直接报诸如“Fatal error: Cannot redeclare class Demo”的致命错误了。但运行没有报错,这也就是php5.3以后引入的命名空间的好处了,就诸如本文开头引用的官方解释中以不同目录下的相同文件名的文件可以存在一样是一个道理了。Demo.php文件中,定义的第一个名称叫做Demo的class类被归并到了DemoNameSpace的命名空间,而定义的第二个名称叫做Demo的class被归并到了DemoNameSpace1的命名空间,故而并不会出现不能重复定义某一个类的致命错误。以上的书写方法是要尽量避免的,因为类外部const常量名与类内部const常量名是一样的,很容易混淆,这里这样书写的目的就是看看不同位置申明的const常量,在调用时的情况;输出结果3已经很明显了,就不再多墨迹解释了。
Demo.php中DemoNameSpace1命名空间下还将const常量constDefine提出,拿到了定义class之外,这又要抓狂了,因为之前的知识是define定义全局常量,const定义class内部常量;这儿却将const拿出来玩了...具体就不再讲解了,Demo.php文件代码以及运行后的结果已经很明确的表明了相关知识。class内部定义的const只能在class的内部调用,采用self::constName形式,而class内部调用命名空间下、class外的const常量,则可以直接使用诸如define定义的常量一样使用。当需要使用该命名空间下、class外定义的const常量时,就使用类似路径形式的方式调用(index.php文件中的输出)。
该例子还有一点说明,就是在index.php中使用了use as语句,看index.php的代码,意义一目了然,new的一个class名称叫Test,但Test这个类并没有在Demo.php中定义,却没有出错,这就在于了use as语句了,具体意义不再解释。
通过上述的了解,namespace关键字可以将实现各种功能的class通过指定不同的命名空间分门别类存放,而且不同命名空间下的class可以同名;另外const常量定义也可以提出到class外部,当然也会有作用范围这么一个“内涵”~
总结下namespace的相关知识:
1、当前脚本文件的第一个命名空间前面不能有任何代码,例如如下代码就是会报致命错误的:
<?php define("GREETING","Hello world!"); namespace DemoNameSpace; class Demo { private $mysqlHandle; public function construct() { echo 'This is namespace of PHP demo ,The Demo magic constant "NAMESPACE" is '.NAMESPACE; }} $Demo = new Demo(); ?>
运行上述代码,会出现致命错误:“Fatal error: Namespace declaration statement has to be the very first statement in xxxx”
2、命名空间下直接new该命名空间中的class名称,可以省略掉use语法,这是php按脚本书写顺序执行导致的。例如如下代码是可以运行的
<?php namespace DemoTest; class Demo { public function construct() { echo 'this is a test script'; }} namespace DemoNameSpace; class Demo { private $mysqlHandle; public function construct() { echo 'This is namespace of PHP demo ,The Demo magic constant "NAMESPACE" is '.NAMESPACE; }}$ Demo = new Demo(); ?>
运行结果4:“This is namespace of PHP demo ,The Demo magic constant "NAMESPACE" is DemoNameSpace”
这个结果表明,同一脚本下new一个没有指定use哪个命名空间时,会顺着该脚本,使用最靠近new语句之前的一个命名空间中的class
3、公共空间:可以简单的理解,没有定义命名空间的方法(函数)、类库(class)、属性(变量)都默认归属于公共空间。这样就解释了为php5.3.0以前版本书写的代码大部分为何在php5.3.0及其以上版本还能正常运行的原因。另外:公共空间中的代码段被引入到某个命名空间下后,该公共空间中的代码段不属于任何命名空间!
命名空间的引入,让php面向对象编程更加的贴切,合理利用命名空间,也可以让项目文件规划,以上就是介绍命名空间的所有内容。
相关推荐:
以上是什麼是命名空間的詳細內容。更多資訊請關注PHP中文網其他相關文章!