隨著流行的 PHP 語言的不斷演變,很多新特性使它在物件導向方面有了進一步的增強。本文通過一些 PHP V5.3 執行個體示範延遲靜態繫結、名稱空間支援、類方法重載以及變數解析和 heredoc 支援。
|
| 需求 除了對 PHP 和 HTML 有基本的認識以外,無需太多其他方面的知識便可閱讀本文。每當文中提到 PHP V5.3 時,指的是 V5.3.0。 |
|
考察的特性
本文主要考察 PHP V5.3 的以下特性:
- 延遲靜態繫結
- 名稱空間
- 類方法重載
- 變數解析和 heredoc
但是,在繼續之前,需要設定 PHP V5.3。
設定
PHP 廣為人知的一個特點就是設定起來有點麻煩。這也許是因為 PHP 是安裝在 Web 服務器(例如 Apache)上的,而且常常需要串連到外部資料庫(例如 MySQL)。而且,某種意義上,PHP 指令碼是嵌入在 HTML 程式碼中的。換句話說,PHP 這種技術橫跨多個複雜的領域。所以,在編寫 PHP 指令碼代碼之前,必須越過很多的障礙。我希望可以改善這一現狀,但是與軟體技術有關的很多事情仍然很困難。
不過,對於那些使用 Apple Macs 的幸運讀者來說,設定過程再簡單不過了:
- 獲得 PHP 二進位安裝檔案(http://www.entropy.ch/software/macosx/PHP/)。
- 在 System Preferences 中關閉 Web Sharing。
- 找到 /etc/apache2/httpd.conf 檔案。
- 在 httpd.conf 檔案中注釋掉下面這行:LoadModule PHP5_module。
- 運行 PHP V5.3 安裝檔案(如果您願意,也可以構建原始碼)。
- 在 System Preferences 中開啟 Web Sharing。
本文的目的不是僅僅介紹如何安裝,所以如果您的平台是 Microsoft Windows 或 Linux,請參閱一些很棒的 PHP 參考書籍(見我在參考資料中推薦的書籍)。
為了檢查 PHP 是否已安裝以及版本是否合適,在 /Library/WebServer/Documents 檔案夾中建立一個名為 PHPinfo1.PHP 的檔案。清單 1 展示了這個指令檔的內容。本文中的所有指令碼都在下載小節提供的壓縮(ZIP)檔案中,所以實際上不需要建立任何檔案。
清單 1. phpinfo1.php
將該指令檔放在 /Library/WebServer/Documents 檔案夾中之後,訪問 http://localhost/PHPinfo1.PHP。應該可以看到類似圖 1 的介面。這裡可能需要用您主機的 IP 位址替換 URL 中的 “localhost”。
圖 1. PHP V5.3.0 安裝成功
延遲靜態繫結
PHP V5.3 擴充了 static **的使用。現在,無需執行個體化類便可訪問靜態類方法和屬性。當類不存在對象,或者不需要對象時,這個特性就比較方便。清單 2 展示了延遲靜態繫結的一個例子。
清單 2. 延遲靜態繫結
<?PHP class A { public static function who() { echo 'Calling who method from class '.__CLASS__; } public static function test() { static::who(); } }
class B extends A { public static function who() { echo 'Calling who method from class '.__CLASS__; } }
B::test(); ?> |
清單 2 中的代碼產生以下輸出:
Calling who method from class B |
|
| 增強物件導向 任 何能增強 PHP 物件導向方面的改變都是受鼓勵的,因為這將導致更可靠的設計和更易於維護的代碼。對於清單 2 中的代碼我有些許微詞,基類(A)和衍生類別(B)中的who()方法是重複的。如果類 B 中不必複製該代碼就好了,但是似乎 PHP V5.3.0 中的__CLASS__文法要求必須這麼做。也就是說,__CLASS__不支援延遲綁定。 清單 2 中使用__CLASS__也許有點勉強,但確實可以說明 PHP V5.3.0 有一個小小的問題。顯然,對於清單 2 中的例子,這不是多大的問題,但是對於有數千行 PHP 代碼的網站來說,就沒那麼簡單了。重複代碼通常意味著重複勞動。 |
|
在 PHP V5.3.0 之前,類 A 中的方法可能被定義為self::who()。不幸的是,這將導致調用類 A 中的函數,而不是子類 B 中的函數。PHP V5.3.0 用static::**修複了這個問題,允許在運行時才引用之前調用的類方法。顯然這就是清單 2 中代碼的目的。
名稱空間
PHP V5.3 提供名稱空間功能,以增強該語言的封裝能力。名稱空間在現代語言中非常常見,例如 C# 和 XML。名稱空間的主要優點是,通過它可以為代碼符號(類、函數和常量)定義獨立的容器,這聽起來有點複雜,其實不然。清單 3 顯示了使用 PHP 名稱空間定義本地和全域字串常量的一個例子。
清單 3. PHP 名稱空間
<?PHP namespace test; define('ASTRING', 'Hello World!'); define('testASTRING', 'Hello World from my namespace!');
echo "<p>My string is: "; echo ASTRING; echo "</p>";
echo "<p>My string is "; echo ASTRING; echo "</p>"; ?> |
清單 3 中的代碼產生以下輸出:
My string is: Hello World from my namespace! My string is: Hello World! |
那麼,代碼中發生了什嗎?第一個define語句在名稱空間test中建立一個字串常量ASTRING。然後,當引用ASTRING字串時,引 擎首先查看本地test名稱空間。這就是為什麼看到本地定義的字串首先顯示。然後,要看到全域定義的字串,只需使用文法ASTRING。有了這些簡單 的規則,便可以使用任意數量的名稱空間,而不必擔心名稱衝突。
有了名稱空間功能,和之前相比,代碼之間的界限更加清晰。而這一點又有助於團隊環境中的代碼整合。換句話說,不同的團隊可以分配他們自己的名稱空 間,當所有團隊成員都遵循這個慣例時,名稱衝突的情況應該會降為零。這也是 5.3.0 版對 PHP 語言在物件導向方面的一個增強。
在 PHP 中,術語重載(overloading)與通常的物件導向上下文稍有不同。在 Java 語言或 C# 中,“重載” 方法是指為不同參數列表提供相同代碼的方法。例如,如果有一個名為draw(String str)的方法,那麼重載的方法可以有以下形式:draw(String str, int i)。這種方法符號名稱被稱作方法簽名,為了便於重載,傳回型別被省略。
在 PHP 中,“重載” 是指動態建立的方法和屬性。這實際上是動態代碼,任何這樣的動態實體都是由所謂的魔術方法(magic methods)來處理。可以在一個類中為各種不同的動作建立這些魔術方法。然後,當代碼中遇到未聲明或不可見的屬性或方法時,便可以調用重載方法。這樣 風格的重載提供了很大程度上的靈活性。
聽起來有些複雜,所以來看看一個具體的例子。清單 4 展示如何使用 PHP 重載調用對象和類方法。
清單 4. PHP 重載
<?PHP class OverloadedMethodTest { public function __call($name, $arguments) { // The value of $name is case sensitive. echo "Calling object method '$name' " . implode(', ', $arguments)。 "n"; }
/** As of PHP 5.3.0 */ public static function __callStatic($name, $arguments) { // The value of $name is case sensitive. echo "Calling static method '$name' " . implode(', ', $arguments)。 "n"; } }
$obj = new OverloadedMethodTest; $obj->runOverloadedTest('in an object context');
OverloadedMethodTest::runOverloadedTest('in a static context'); // As of PHP 5.3.0 ?> |
清單 4 中的代碼產生以下輸出:
Calling object method 'runOverloadedTest' in an object context Calling static method 'runOverloadedTest' in a static context |
在清單 4 中,注意重載的代碼是如何根據調用代碼來推斷方法名和參數的:
$obj->runOverloadedTest('in an object context');
OverloadedMethodTest::runOverloadedTest('in a static context'); // As of PHP 5.3.0 |
要使用這種能力,程式員需要承擔較大的責任。雖然重載為編寫靈活的代碼提供了便利,但同時也為錯誤提供了土壤。所以,使用重載時應該謹慎,並且要有嚴格的代碼測試紀律。
變數解析和 heredoc
PHP 的優勢之一在於字串解析。PHP 對於字串的長度沒有限制,只要主機的可用記憶體夠大就行。清單 5 展示了使用 PHP 時擁有的靈活性。
清單 5. PHP 解析
<?PHP $beverage = 'coffee'; // The following works; "'" is an invalid character for variable names echo "$beverage's taste is great"; // The following won't work; 's' is a valid character for variable names but the echo "He drank a number of $beverages"; variable is "$beverage" echo "He drank some $s"; // works echo "He drank some s"; // works ?> |
清單 5 中的代碼產生以下輸出:
coffee's taste is great He drank a number of He drank some coffees He drank some coffees |
清單 5 中的代碼並不是直到 PHP V5.3.0 才有的。這裡給出這段代碼,只是為了提醒您字串處理支援和一些解析規則。但是,PHP V5.3.0 增加了增強 heredoc 文法支援。清單 6 顯示了一個簡單的例子。
清單 6. PHP V5.3.0 heredoc 的應用
<?PHP echo >>>"FOOBAR" Hello World! FOOBAR; ?> |
清單 6 中的代碼產生以下令人驚歎的輸出:
那麼,清單 6 有什麼特別之處呢?PHP V5.3.0 中的 heredoc 支援使用雙引號。其優點主要在於,雙引號中的內容不會被解析,這樣便有了更大的靈活性。基本上,這隻是在已經強大的字串支援的基礎上增加了更多的靈活 性。PHP V5.3.0 的線上參考包括更多關於這個主題和 PHP V5.3.0 其他相關主題的資料。
結束語
PHP 是一項有吸引力的技術。它為拼湊式(pick-and-mix)網站開發提供了便利。您可以為網站增加資料庫,PHP 語言為此提供了所需的綁定。您不需要重量級的應用伺服器或 servlet 技術。換句話說,只需極小的投資 — 無論是財務上還是智力上的投資,就可以控制環境。
PHP 語言在不斷演變,很高興看到 V5.3.0 中的很多改進有效地增強了物件導向方面。這有助於 PHP 在與那些更重量級(也更昂貴)的 Web 設計方法的競爭中勝出。
在本文中,我討論了延遲靜態繫結、名稱空間支援、類方法重載和 heredoc 支援。這隻是 PHP V5.3.0 的冰山一角。還有很多其他專題,例如遷移到 V5.3.0。請參閱參考資料小節,獲得關於這些專題和其他專題的詳細資料。