用PEAR來寫你的下一個php程式
最後更新:2017-02-28
來源:互聯網
上載者:User
程式 你可能已經是個PHP的老手了,寫了很多非常棒的代碼。但是,如果你現在要把它們加入到你現在的項目中去,是否有些吃力?你的朋友想使用你的代碼作為他的項目中的一個模組,但是你發現你們使用了截然不同的編碼風格,讓他適應,甚至不如重寫一個!
請跟我來,使用PEAR標準編寫你的PHP程式吧,你的程式將會擁有更大的活力,你的程式和代碼將會很方便地和其他高手的代碼融合在一起,PEAR就象CPAN對於PERL一樣,會讓PHP產生更高的能量。
什麼是PEAR
PEAR是PHP擴充與應用庫(the PHP Extension and Application Repository)的縮寫。它是一個PHP擴充及應用的一個代碼倉庫,簡單地說,PEAR就是PHP的CPAN。
為什麼要使用PEAR?
PHP是一個非常優秀的指令碼語言,簡潔、高效,隨著4.0的發布,越來越多的人使用它來進行動態網站的開發,可以說,PHP已經成為最優秀的INTERNET開發語言之一,尤其對於那些需要能夠快速、高效地開發中小規模的商業應用的網站開發人員,PHP是其首選的語言。但是隨著PHP的應用的不斷增多,對於這些應用缺乏統一的標準和有效管理,因此,PHP社區很難象PERL社區的人們那樣方便的共用彼此的代碼和應用,因為PHP缺乏象CPAN那樣的統一的程式碼程式庫來分類管理應用的代碼模組(熟悉PERL的人都知道,CPAN是一個巨大的PERL的擴充模組倉庫,編寫的應用模組可以放在CPAN下面的適當的分類目錄下面,其他的人可以很方便地複用,當然,你編寫應用模組時候也需要遵守其中的準則。)
為此,PEAR就應運而生了,並且從4.04開始,隨著PHP核心一起被分發。
PEAR能給我帶來什麼好處?
1.如前所述,PEAR按照一定的分類來管理PEAR應用程式碼程式庫,你的PEAR代碼可以組織到其中適當的目錄中,其他的人可以方便地檢索並分享到你的成果。
2.PEAR不僅僅是一個代碼倉庫,它同時也是一個標準,使用這個標準來書寫你的PHP代碼,將會增強你的程式的可讀性,複用性,減少出錯的幾率。
3.PEAR通過提供2個類為你搭建了一個架構,實現了諸如解構函式,錯誤捕獲功能,你通過繼承就可以使用這些功能。
PEAR的編碼規則
PEAR的編碼規則包括縮排規則,控制結構,函數調用,函數定義,注釋,包含代碼,PHP標記,檔案頭的註解區塊,CVS標記,URL範例,常量的命名這11方面。下面簡要地介紹一下:
縮排規則:
PEAR中需要使用4個空格來縮排代碼,並且不使用TAB。如果你使用VIM,將下列設定放入你的~/.vimrc中:
set expandtab
set shiftwidth=4
set tabstop=4
如果,你使用Emacs/XEmacs,需要把indent-tabs-mode 設定成nil。
不過你象我一樣喜歡用(X)Emacs編輯PHP檔案,我強烈推薦你安裝PHP-MODE,這樣當你編寫PEAR代碼的時候,它會自動調整你的縮排風格,當然PHP-MODE還有許多很優秀的特性,你可以從資源清單中的地方下載最新版的PHP-MODE。
控制結構:
這裡所說的控制結構包括: if for while switch 等。對於控制結構,在關鍵字(如if for ..)後面要空一個格,然後再跟控制的圓括弧,這樣,不至於和函數調用混淆,此外,你應該盡量完整的使用花括弧{},即使從文法上來說是可選的。這樣可以防止你以後需添加新的程式碼時產生邏輯上的疑惑或者錯誤。這裡是一個範例:
if ((條件1) && (條件2)) {
語句1;
}esleif ((條件3) || (條件4)) {
語句2;
}else {
語句3;
}
函數調用:
對於函數調用,函數名和左括弧( 之間不應該有空格,對於函數參數,在分隔的逗號和下一個參數之間要有相同的空格分離,最後一個參數和右括弧之間不能有空格。下面是一個標準的函數調用;
$result = foo($param1, $param2, $param3);
不規範的寫法:
$result=foo ($param1,$param2,$param3);
$result=foo( $param1,$param2, $param3 );
此外,如果要將函數的返回結果賦值,那麼在等號和所賦值的變數之間要有空格,同時,如果是一系列相關的指派陳述式,你添加適當的空格,使它們對齊,就象這樣:
$result1 = $foo($param1, $param2, $param3);
$var2 = $foo($param3);
$var3 = $foo($param4, $param5);
函數定義:
函數定義遵循"one true brace"習俗:
function connect(&$dsn, $persistent = false)
{
if (is_array($dsn)) {
$dsninfo = &$dsn;
} else {
$dsninfo = DB::parseDSN($dsn);
}
if (!$dsninfo || !$dsninfo['phptype']) {
return $this->raiseError();
}
return true;
}
如上所示,選擇性參數要在參數表的末端,並且總是盡量返回有意義的函數值。
關於注釋:
對於類的線上文檔,應該能夠被PHPDoc轉換,就象JavaDoc那樣。PHPDoc也是一個PEAR的應用程式,更詳細的介紹你可以去 http://www.phpdoc.de/ 查看。除了類的線上文檔,建議你應該使用非文檔性質的注釋來詮釋你的代碼,當你看到一段代碼時想:哦,我想不需要在文檔裡去仔細描述它吧。那麼你最好給這段代碼作一個簡單的注釋,這樣防止你會忘記它們是如何工作的。對於注釋的形式,C的 /* */和C++的//都不錯,不過,不要使用Perl或者shell的#注釋方式。
包含代碼:
無論什麼時候,當你需要無條件包含進一個class檔案,你必須使用requre_once;當你需要條件包含進一個class檔案,你必須使用include_once;這樣可以保證你要包含的檔案只會包含一次,並且這2個語句共用同一個檔案清單,所以你無須擔心二者會混淆,一旦require_once 包含了一個檔案,include_once不會再重複包含相同的檔案,反之亦然。
PHP代碼標記:
任何時候都要使用<?php ?>定義你的php代碼,而不要簡單地使用<? ?>,這樣可以保證PEAR的相容性,也利於跨平台的移植。
檔案頭的注釋聲明:
所有需要包含在PEAR核心發布的PHP代碼檔案,在檔案開始的時候,你必須加入以下的注釋聲明:
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4.0 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Original Author |
// | Your Name |
// +----------------------------------------------------------------------+
//
// $Id$
對於不在PEAR核心程式碼程式庫中的檔案,建議你也在檔案的開始處有這樣一個類似的註解區塊,標明著作權,協議,作者等等。同時也在第一行加入VIM的MODELINE,這樣在VIM中能夠保持PEAR的代碼風格。
CVS標記:
如上面所展示那樣,在每個檔案中加入CVS的ID標記,如果你編輯或修改的檔案中沒有這個標記,那麼請加入,或者是替換原檔案中相類似的表現形式(如"Last modified"等等)
URL樣本:
你可以參照RFC 2606,使用"www.example.com"作為所有的URL樣本。
常量命名:
常量應該盡量使用大寫,為了便於理解,使用底線分割每個單詞。同時,你應該常量所在的包名或者是類名作為首碼。比如,對於Bug類中常量應該以Bug_開始。以上是PEAR的編碼規則,詳細的編碼規則可以參考PEAR中的CODING_STANDDARD檔案的說明。為了更好地理解這些編碼規則,你也可以參考一下現有PEAR核心模組的代碼。
開始使用PEAR
PEAR
使用PEAR很簡單,你只需這樣定義你自己的PEAR程式:
require_once "PEAR.php";
class your_class_name extends PEAR{
你的類定義...
}
當然,你需要遵守前面說的PEAR的編碼規則,之後你就可以在你的類內部實現你要做的事情了。下面,我們展開討論一下,實際上PEAR為我們提供了2個預定義類:
PEAR:這是PEAR的基類,所有的PEAR擴充都要從它繼承派生出來。
PEAR_Error:PEAR的錯誤處理的基類,你可以選擇派生出自己的錯誤處理的類。
一般來說,你不應該直接建立PEAR的執行個體,而是要自己派生出一個新的類,然後再建立這個新類的執行個體。作為基類,PEAR給我們提供了一些有用的功能,最主要的就是解構函式和錯誤處理
解構函式
PHP支援建構函式,但是並不支援解構函式,不過,PHP提供register_shutdown_function()這個函數,從而能夠在指令碼終止前回調註冊的函數,因此PEAR利用這個特性,提供了解構函式的模擬。假如你有一個PEAR的子類,叫做mypear,那麼在mypear類中,你可以定義一個函數,函數名是底線加上你的類名,_mypear(),這個函數就是這個類的解構函式。不過這個解構函式和C++中的解構函式不太一樣,它不會在對象被刪除的時候執行,而是在指令碼結束的時候,畢竟這隻是一個模擬。由於是使用了register_shutdown_function(),所以在你的解構函式裡,列印的資訊將不會返回瀏覽器中。此外,在你的建構函式中,需要調用一下它的父類的建構函式,因為PHP不會自動調用父類的建構函式,而解構函式需要在PEAR的建構函式中註冊,我們可以看看PEAR的原始碼:
<code>
function PEAR() {
if (method_exists($this, "_".get_class($this))) {
global $_PEAR_destructor_object_list;
$_PEAR_destructor_object_list[] = &$this;
}
if ($this->_debug) {
printf("PEAR constructor called, class=%s\n",
get_class($this));
}
.....
function _PEAR_call_destructors() {
global $_PEAR_destructor_object_list;
if (is_array($_PEAR_destructor_object_list) && sizeof($_PEAR_destructor_object_list)) {
reset($_PEAR_destructor_object_list);
while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
$destructor = "_".get_class($objref);
if (method_exists($objref, $destructor)) {
$objref->$destructor();
}
}
//清空登入的對象列表,
//防止重複調用
$_PEAR_destructor_object_list = array();
}
}
....
register_shutdown_function("_PEAR_call_destructors");
</code>
上面這段代碼展示了PEAR是如何?解構函式的,在構件函數中,將檢查當前類中是否有解構函式,如果有,那麼將把當前類的引用放入一個全域列表中,在_PEAR_call_destructors中,則檢查這個全域列表中的每個元素是否存在相應的解構函式,如果有,則調用它,最後將全域列表清空。
在PEAR.php的最後一行代碼,則調用register_shutdown_function("_PEAR_call_destructors"),註冊_PEAR_call_destructors,這樣,當指令碼執行完畢的時候,PHP會回調這個函數。使用解構函式,你可以在處理完使用者的請求,退出之前做一些必要的"善後"工作,典型的例子是,你可以關閉開啟的檔案,斷開資料庫的串連,將某些資料存入磁碟等等。
錯誤處理
PEAR中可以讓你有很多的方式來處理錯誤,你不僅僅是簡單地返回一個錯誤碼,或者錯誤的資訊,而是可以返回一個PEAR_Error對象,或者是由PEAR_Error派生出來的新的錯誤對象。
PEAR中的錯誤對象的並沒有限定具體的輸出形式,它可以僅僅是捕獲錯誤,不給使用者返回太多的資訊,也可以是去回調一個特殊錯誤處理函數,同時,即使輸出錯誤資訊,它也強迫你必須要是HTML形式,你可以輸出XML,CSV形式,或者是其他你自己定義的形式,你只需要從PEAR_Error派生一個新的類,然後在適當的時候建立並"拋出"這個新類的對象就可以了。
簡單的錯誤處理:
在PEAR中,最簡單的錯誤處理是"拋出"這個錯誤,你只要簡單地建立並返回一個PEAR_Error的對象就可以了。下面是一個簡單的例子:
<code>
function myconnect($host = "localhost", $port = 1080)
{
$fp = fsockopen($host, $port, $errno, $errstr);
if (!is_resource($fp)) {
return new PEAR_Error($errstr, $errno);
}
return $fp;
}
$sock = myconnect();
if (PEAR::isError($sock)) {
print "connect error: ".$sock->getMessage()."<BR>\n"
}
</code>
如上面代碼所展示的,在執行一段可能產生錯誤的代碼後,你需要使用PEAR的isError來檢測是否存在錯誤,並且可以使用PEAR_Error的getMessage來取得最近一次的錯誤資訊。注意:一定要在關鍵的地方使用使用PEAR::isError
使用raiseError
PHP4.0.5以後,PEAR多了2個函數:
setErrorHandling($mode, $options = null)
raiseError($message = null, $code = null, $mode = null,$options = null, $userinfo = null)
前者可以設定PEAR預設的錯誤處理模式,後者是一個封裝函數,返回一個PEAR_Error的對象,和直接建立並返回PEAR_Error的對象略有不同的是,如果省略$mode,$options等參數,它會使用預設值來建立這個PEAR_Error的對象,這些預設值你可以使用setErrorHandling()來定製。
PEAR_Error
PEAR_Error是PEAR的錯誤對象的一個基類,和PEAR不同,一般來說,你可以直接建立PEAR_Error的執行個體,建立方式:
$error = new PEAR_Error($message, $code, $mode, $options, $userinfo);
$message是你的錯誤資訊,$code是該錯誤的錯誤號碼,後3個參數是緊密聯絡的:
$mode:是這個錯誤的處理模式,可以下列常量:
PEAR_ERROR_RETURN:僅僅返回該錯誤對象(預設方式)
PEAR_ERROR_PRINT:在構建函數中列印這個錯誤資訊,但是當前程式會繼續運行。
PEAR_ERROR_TRIGGER:使用PHP的trigger_error() 觸發一個錯誤,如果你已經設定了錯誤處理函數,或者你把PHP的錯誤處理層級設定為E_USER_ERROR,那麼當前程式將會被終止。
PEAR_ERROR_DIE:列印錯誤並退出,程式終止。
PEAR_ERROR_CALLBACK:使用一個回呼函數或者方法來處理當前錯誤,程式終止。
$options:這個參數只有在$mode是PEAR_ERROR_TRIGGER和PEAR_ERROR_CALLBACK的時候才起作用,如果是PEAR_ERROR_TRIGGER,$options必須是E_USER_NOTICE, E_USER_WARNING 或 E_USER_ERROR這3個常量的一個,同PHP中trigger_error的值一致。如果$mode是PEAR_ERROR_CALLBACK,$options可以是一個字串,內容是要回調的函數名,也可以是一個2元素的數組,分別是一個物件變數,和一個字串(標明要調用的方法)。
$userinfo:存放附加的使用者資訊,你可以把相關的調試資訊放在這裡。
PEAR_Error中有一些常用的方法,這些方法在PHP文擋沒有描述,這裡一一列出:
int getMode:返回當前的錯誤處理模式,整型。
string getMessage:返回當前完整的錯誤資訊,字串。
mixed getCallback:返回當前的回調資訊,可能是所回調的函數名,或者是(對象,方法)的數組。
int getCode:返回整型的錯誤碼。
string getType:返回錯誤的類型,也就是當前的類名,字串。
string getUserInfo:返回附加的使用者資訊,字串。
string getDebugInfo:內容同上。
string toString:返回當前對象的詳細字串描述,內容包括錯誤處理的模式,層級,錯誤資訊,錯誤碼,相關回呼函數等等。
總結
至此,對於PEAR的介紹就結束了。概括地說,如果你要做一個PEAR的擴充應用,需要這麼做:
require_once "PEAR.php"
使用class your_pear_extend extends PEAR{}定義你的新類。
在你的類的建構函式中,調用父類PEAR的建構函式:
function your_pear_extend{
$this->PEAR();
...
}
如果需要,定義你的解構函式 _your_pear_extend
如果需要,從PEAR_Error派生出你自己的錯誤處理類
設定你的錯誤處理模式,並在適當的時候觸發錯誤。
在執行可能產生錯誤的代碼後,用PEAR::isError($obj)捕獲相應的錯誤。
實現你自己的功能。
在最新的PHP4.05的PEAR核心發布裡,已經有不少優秀的應用模組了,比如:PHPDoc,Cache,HTML...當然,相對於CPAN來說,PEAR只是剛剛起步,需要PHP社區的人們的共同努力,來完善它,增強它,PHP才會越來越強大。
相關資源
Pear首頁
PHP首頁
PHPDoc首頁,可以從你的PEAR應用源碼產生類似JAVADOC的API文檔
PHP-Mode for XEmacs/Emacs,為emacs/xemacs提供php的文法支援,能夠很好支援pear代碼風格
Vim首頁,非常優秀的一個編輯器,對php的支援也很好
作者簡介
潘凡(Night Sailer):北京賽迪網資訊技術有限公司。主要從事是資料的分析和轉換,以及相關的開發工作。擅長使用VB,PERL,PHP進行開發以及Linux的中文化工作。近期興趣是Perl,Php與XML的應用,PHP的MVC開發模式,PERL-GTK的使用。您可以通過 E-mail:nightsailer@hotmail.com跟他聯絡。