對于一個開發人員,文檔總是最感到頭疼的事情之一。而且,很可能你對待文檔會采取截然不同的2種態度:
當你使用別人的代碼庫的時候,最希望得到的是它的技術文檔,尤其是當時間很緊,而你又不得不硬著頭皮去讀那些生澀的代碼的時候。
當寫你自己的程序的時候,最不希望做的事情卻是給它編寫專門的技術文檔,你會以種種理由給自己開脫:我的代碼已經足夠清晰了,完全不用再為它重新編寫文檔了……
也許是為了緩解這種矛盾,有很多工具可以幫助你,通過從源代碼中抽取相應的注釋,可以自動生成相應的api文檔。java中的javadoc,perl中的pod2man。相比之下,php以前似乎缺乏相應的工具,不過,隨著phpdoc的不斷完善,這種局面已經大大改觀。
在第一篇pear的編碼規則中有一條,pear程序中的注釋應該能夠被phpdoc轉換。由此可見,phpdoc在pear中的作用可不小。今天,我們將詳細討論phpdoc,這個優秀的pear程序。
1. 什么是phpdoc
PHPDoc是PEAR下面的一個非常優秀的模塊,它的目標是實現類似javadoc的功能,可以為你的代碼快速生成具有相互參照,索引等功能的API文檔。如果你使用過javadoc生成的文檔(如jdk的文檔),你會非常清楚,如果你沒有用過,那么下面是一個phpdoc生成它自己的文檔頁面的截圖:
從圖上可以知道,phpdoc生成的文檔和JAVADOC很相似,它有多種的索引方式:
Packageindex:這是按照模塊來索引
Classtree:這是按照你的php類的繼承關系,可以生成一個樹狀的索引
Modulegroups:這是按照模塊劃分
Elementlist:這是你的所有元素(類,方法,過程/函數,變量)的字母順序的索引
2. phpdoc的結構及功能
由于phpdoc本身也是符合pear的應用程序,我們首先了解一下它的結構。phpdoc是全部采用OOP的思想來編寫的,這也是PEAR所推薦的方式,phpdoc的工作原理:
從設計上來說,phpdoc使用了2個超類:PhpdocObject和PhpdocError。這是整個PHPDOC的基本類,這種方式也是PEAR所推薦的,也就是說當你編寫你自己的應用框架的時候,最好能夠有一個基本的超類,而其他的子類或者是功能類都有一個共同的祖先。在掃描源代碼過程中,PHPDOC使用的是類似GREP的形式,并沒有象我們通常想的那樣,使用正則表達式來實現,根據作者的解釋,他曾經嘗試過使用正則表達式,但是資源的占用和處理速度都很難令人滿意,因此采用了這種非常規的形式,具體的實現有興趣的讀者可以參看源代碼。我認為PHPDOC令人滿意的另一方面是其分析結果是以XML形式保存的,這樣就意味著其他的應用程序很容易可以共享這個數據,同時PHPDCO也提供了相應的接口,你可以實現這個接口,把API文檔生成其他的形式,比如PDF,LATEX,WORD等等。目前,PHPDOC的分析結果可以以HTML形式表現,以后可能會有更多的形式。即使是HTML形式,由于使用了模板機制(他使用了PEAR的IT和ITX模塊來實現),你可以很方便地定制成你自己需要的風格,
3. PHPDoc基礎
PHPDoc是從你的源代碼的注釋中生成文檔,因此在給你的程序做注釋的過程,也就是你編制文檔的過程。
從這一點上講,PHPdoc促使你要養成良好的編程習慣,盡量使用規范,清晰文字為你的程序做注釋,同時多多少少也避免了事后編制文檔和文檔的更新不同步的一些問題。
編制符合PHPDoc規范的注釋是非常重要的,掌握了這一點,基本上就可以利用PHPDoc為你工作了。
注釋在PHPDoc中分為文檔注釋和非文檔注釋
3.1 文檔注釋
文檔注釋實際上是一些特殊形式的多行注釋,一般是放在你需要注釋的特定的關鍵字(這些關鍵字是指將會被phpdoc分析的那些關鍵字,相關的關鍵字列表請參看后面第4節的說明)前面。下面是一個文檔注釋的例子:
|
<b>PhpdocObject</b>PhpdocObjectCommon base class of all phpdoc classes<b>private class PhpdocObject </b>Common base class of all phpdoc classesAs a kind of common base class PhpdocObject holdsconfiguration values (e.g. errorhandling) and debuggingmethods (e.g. introspection()). It does not have aconstructor,so you can always inheritig Phpdoc classes from |
3.2 非文檔性注釋
如果你的注釋沒有放在那些phpdoc指定的關鍵字前面,那么phpdoc認為你所作的這些注釋是屬于非文檔注釋,將不會被phpdoc所分析,也不會出現在你產生的api文當中。
3.3 如何書寫你的文檔性注釋
從3.1 我們可以看到,一個文檔性的注釋,是由3個部分組成的,分別是:功能簡述區,功能詳細說明區,文檔標記區。
首先,第一行是一個注釋開始的標志"/**",然后是回車,從第2行開始就是功能簡述區,功能簡述區是以縮進的"*"開始的,在簡述的正文和這個"*"號之間用空格分隔(注意,在文檔中,都是以*開始,并且這些*保持對齊的縮進格式)。功能簡述的正文一般是簡明扼要地說明這個類,方法或者函數的功能,功能簡述的正文在生成的文檔中將顯示在索引區。
在功能簡述區后面是一個空的注釋行,用來分割簡述區和詳細說明區。功能詳細說明區也是以縮進的'*"來引導的,這部分主要是詳細說明你的API的功能,用途,如果可能,也可以有用法舉例等等。在這部分,你應該著重闡明你的API函數或者方法的通常的用途,用法,并且指明是否是跨平臺的(如果涉及到),對于和平臺相關的信息,你要和那些通用的信息區別對待,通常的做法是另起一行,然后寫出在某個特定平臺上的注意事項或者是特別的信息,這些信息應該足夠,以便你的讀者能夠編寫相應的測試信息,比如邊界條件,參數范圍,斷點等等。
在功能詳細說明區后面,是空白的注釋行,然后是文檔標記區,你可以在這些書寫相關的文檔標記(這些文檔標記的用法請參考后面的第4節),指明一些技術上的細節信息,最主要的是調用參數類型,返回值極其類型,繼承關系,相關方法/函數等等。多個文檔標記應該使用相同的縮進,組成一個"標記塊",便于閱讀和分析。
在文檔標記區下面的一行就是注釋結束行"*/",注意,在注釋結束標記*/后面應該直接跟一個回車,不要另外附加其他的東西,否則可能造成PHPDOC分析出錯。
以上就是書寫一個文檔性注釋的基本方法,下面我們討論一下書寫文檔時的規范和技巧。
3.4 文檔書寫指南
在你描述你的代碼的用途或者是功能的時候,最好能夠遵循大多數人的習慣,通俗地講就是"你告訴我的信息正是我想要知道的"。為此,這里將介紹一些書寫文檔注釋的技巧和規范,希望能夠對你有所幫助:
/** * 設置用戶記錄集 * * @param text 給定的表名 */ function set_user_record($table) { |
你從上面這段注釋中能夠知道什么?因此,這段注釋實際上是廢話,因為你從函數名稱上是可以看出的,下面是改進后的:
/** * 打開系統用戶表并設置為當前用戶記錄集,此記錄集將用于隨后相關用戶數據更新操作的缺省記錄集。 |
4. PHPDoc關鍵字及文檔標志
4.1 關鍵字
class 、function 、var 、include (include_once, require, require_once) 、define
在以上這些關鍵字前面所做的注釋,都被認為是文檔性注釋。
4.2 文檔標記
說明:使用范圍是指該標記可以用來修飾的關鍵字,或其他文檔標記@abstract 使用范圍:class, function, var
說明當前類是一個抽象類。
注釋:從PHP語言角度來說,它并不象JAVA,C++那樣,支持抽象類這個概念。也沒有相應的關鍵字來修飾某個類是抽象類。由于PHPDOC實際上大部分是借鑒了JAVADOC的做法,因此很多文檔標記也是直接從JAVADOC中沿襲過來,如abstract,access,final等等。雖然這些特性沒有從語言級別得到支持,不過從使用者角度來遵循這些特性,仍是值得推薦的。
舉例:
/*** 這是一個繪五星圖案的抽象類.* @abstract*/class paint_start { /** * 繪制數量 * @abstract */ var $number; /** * 繪制五星圖案 * @abstract */ function paint() { ; }} |
指明這個變量、類、函數/方法的存取權限。如果你的函數是內部使用,你應該指明它為private,這樣的好處是,即使PHP不能阻止其他的人使用你的私有數據,但是至少你向你的用戶傳達這樣的信息,這是一個私有的函數,因此不保證在將來的版本中仍存在;對于使用者而言,表示為@private的數據和方法,你不應該直接使用,即使你可以這樣做。
舉例:
/*** 這是一個繪五星圖案的抽象類.* @abstract* @access public*/class paint_start { /** * 繪制數量 * @abstract * @access private */ var $number; /** * 繪制五星圖案 * @abstract * @access public */ function paint() { ; }} |
指明作者信息,依次是作者姓名,email地址,其他的通訊信息。如果有多個作者,按照其先后次序,使用多個@author依次列出:
指出兄弟類、函數或者是變量.這些函數、類、變量等有相似的信息和并實現相同的功能。比如,調用和返回的參數的個數和類型相同,實現的功能也一樣。這種情況,你可以使用@brother 或者 @sister指明它的兄弟函數,無須在重復書寫函數的功能等信息了。
舉例:
/*** 這是一個繪五星圖案的抽象類.* @abstract* @access public*/class paint_start { /** * 繪制數量 * @abstract * @access private */ var $number; /** * 繪制五星圖案 * @abstract * @access public */ function paint() { ; } /** * @brother paint() */ function draw() { ; }} |
@const[ant] label [description] 使用范圍:define
指明常量
這個標記實際上是用來說明php的define關鍵字定義的常量。
@copyright description 使用范圍:class, function, var, module, define, use
指明版權信息。
@deprec[ated] label 使用范圍:class, function, var, module, define, use
指明不推薦或者是廢棄的信息.
如果你的某個函數或者方法,已經被新的函數方法替代,或者是已經廢棄,不希望讀者繼續使用。那么你可以使用這個標志告訴讀者,這個函數只是為了保持兼容性而保留的,它不被推薦使用,如果它已經被其他函數替代,也要指出這個替代者。
例子:
/*** 過時的類** @deprec 1.5-2000/12/06* @access public*/function dontUseMeAnyMore() { print "Don't use me any more. I have been deprecated.";} |
@exclude label 使用范圍:class, function, var, module, define, use
指明當前的注釋將不進行分析,不出現在文擋中
@final 使用范圍:class, function, var
指明這是一個最終的類、方法、屬性,禁止派生、修改。
舉例:
/** * 圓周率 * @final */ var $PI = 3.1415926; |
@global (object objecttype|type) [$varname] [description] 使用范圍:function
指明在此函數中引用的全局變量
舉例:
/*** Simuliert include_once in PHP 3.** @global array $__used_files 已經include的文件列表* @access public*/function include_once($filename) { global $__used_files; if (!isset($__used_files["include_once"][$filename])) { $__used_files["include_once"][$filename] = true; include($filename); }} |
@include description 使用范圍:use
指明包含的文件的信息。
舉例:
/*** 抽象繪圖類的定義.** @includeFunction: _require_*/require("abstract.php"); |
@link URL description 使用范圍:class, function, var, module, define, use
定義在線連接,如上面3.4中講到的,你可以使用@link添加適當的在線鏈接。
例如:@link http://www.phpdoc.de/ PHPDoc Home
@magic description
這個標記在phpdoc中沒有說明,具體用法現在仍不清楚
@module label 使用范圍:module
定義歸屬的模塊信息,label是模塊的名字,擁有相同的模塊名字的函數在索引分類中將被組合在一起。如果你沒有使用OOP的思想來編寫PEAR代碼,那么建議你使用這個標記把相關的函數歸集到相應的模塊下面,這樣你的整體的框架不至于過于零散和混亂。
@modulegroup label 使用范圍:module
定義歸屬的模塊組 label是這個模塊組的名字,如果你的應用程序的模塊很多,你可以把不同的模塊按照邏輯功能的不同,劃分成相應的模塊組,這樣,你的應用框架可以有比較清晰的邏輯關系。這是對于沒有使用OOP編程的來說的,如果使用OOP的思想,沒有必要使用模塊組的概念,因為直接使用"包-超類--基類--子類"的形式來體現你的框架結構要比使用"包-模塊組-模塊"的形式好的多。
@package label 使用范圍:class, module
定義歸屬的包的信息,label 是這個包的名字。相同的包的名字的類在最終文檔索引中將被分在一起。實際上,包還可以理解為不同的名字空間,雖然PHP沒有名字空間的概念,但是你可以把相關的類、模塊都歸屬于同一個包,這樣,相當于組織了一個名字空間,當然,你的應用框架可能會有不同的包,可惜的是,這種情況下從語法上是得不到名字空間這種保證的,你只能通過人為地去避免不同的包的函數或者類重名。
@param[eter] (object objecttype|type) [$varname] [description] 使用范圍:function
定義函數或者方法的參數信息。這是最常使用的文檔標記了。
ojecttype 是對象的類名,type 指出這個參數的類型,它可以是下列類型:
* * @param array $tags array of tags returned by getTags * @param array $data array where the allowed tags |
@return (object objecttype|type) [$varname] 使用范圍:function
定義函數或者方法的返回信息。
返回信息的類型同@param一樣,$varname是返回變量的名稱,可有可無。不同的是@return只有一個,不會出現多個@return
@see (function()|$varname|((module|class)::)(function()|$varname)) [, ...] 使用范圍:class, function, var, module, define, use
定義需要參考的函數、變量,并加入相應的超級連接。這也是較常用的標記。對于相關的函數,變量,你可以使用@see來增加一個到相關函數和變量的鏈接。多個相關的函數、變量寫在一行,中間用逗號來分隔。
參考的函數、變量如果是當前類或模塊的,那么你可以直接寫函數、或者變量的名,如果是函數那么要在函數名后面加上括號(),變量名要加上$。需要注意的,這里所謂的變量名也應該是你用@var來說明過的,否則,phpdoc將無法找到相關的參照而報錯。
如果你想引用其他類或者其他模塊的函數或者是變量,那么,你可以在函數名、變量名前面加上類或模塊的名字作為范圍指示,中間用::來分隔。
下面是一些例子:
@see $run_time,$idle_time,$begin_time,$end_time
@see getRuntime(), getIdletime(),getBegintime(),getEndtime()
@see TIME::$run_time, TIME::getBegintime()
@since label 使用范圍: class, function, var, module, define, use
指明該api函數或者方法是從哪個版本開始引入的。
@static 使用范圍:class, function, var
指明變量、類、函數是靜態的。
@throws exception [, exception] 使用范圍: function
指明此函數可能拋出的錯誤異常,極其發生的情況
如果你預料到在這個函數中有產生異常的條件,那么你可以使用@throws標記來說明這些異常是什么,什么情況下產生異常。比如,讀取磁盤文件出錯,無法連接數據庫,網絡連接超時或者是在一些情況下,你"故意"拋出的異常等等。
@todo 使用范圍:class, function, module, use
指明應該改進或沒有實現的地方
@var[iable] (object objecttype|type) [$varname] [description] 使用范圍:var
定義說明變量/屬性。
object objecttype|type 定義你的變量的類型,同@param一樣
$varname 該變量的名字,你可以從其他地方使用@see來引用這個名字
description 對變量的描述
@version label 使用范圍:class, function, module, use
定義版本信息.
你當然可以自己手工寫這些版本信息,不過PEAR推薦你使用CVS的$Id標記來自動標示你的版本信息。形式如下:
@version $Id
這樣,當你checkout的時候,CVS自動會擴展成: @version $Id: PhpdocParserCore.php,v 1.4 2001/02/18 14:45:27 uw Exp
5. 生成文檔
5.1 安裝PHPDOC
安裝PHPDOC很簡單,實際上因為它已經隨同PHP 4.05一同發布了,所以如果你的PHP是4.05,那么在PEAR目錄下面會發現PHPDOC這個模塊.如果你沒有發現,你可以從PHPDOC的CVS獲得一份最新的源碼.
5.2 運行PHPDOC
運行PHPDOC需要做一些準備工作,首先要調整你的PHP.INI的參數,
因為PHPDOC運行的時間比一般的PHP應用要長,很可能會超過你在PHP.INI中定義的最大運行時間(缺省是30秒),根據作者的建議:PIII,60秒,120秒PII,240秒MMX200,480秒如果配置更低的話。如果出現超時,你可以自己適當延長這些數值。
在php.ini中修改:
;;;;;;;;;;;;;;;;;;;; Resource Limits ;;;;;;;;;;;;;;;;;;;;max_execution_time = 480memory_limit = 8388608 |
如果你不愿意或者沒有修改php.ini的權限,那么你可以使用set_time_limit()函數來設置這個時間,使用方法: set_time_limit(480);
設置從此點開始,運行480秒后才超時。將這個函數加在index.php中,就可以和修改php.ini達到同樣的效果。
其次,你要修改phpdoc目錄下面的index.php文件:
// Directory with include filesdefine("PHPDOC_INCLUDE_DIR", "c:/www/apache/doc/"); |
// Important: set this to the Linebreak sign of your system!
define("LINEBREAK", "/r/n");
下面,為你的要生成文檔的應用程序做一些定制工作:
// Sets the name of your application.// The name of the application is used e.g. as a page title$doc->setApplication("PHPDoc");setApplication()用來設置你的應用程序的名稱,將PHPDOC替換成你應用程序的名字。// directory where your source files reside:$doc->setSourceDirectory(PHPDOC_INCLUDE_DIR);setSourceDirectory()設置你的應用程序的PHP源文件所在的目錄, |
5.3 實用工具
通過PHPDOC的INDEX.PHP雖然可以產生文檔,但是畢竟不是那么方便,這里我給出了一個自己寫的shell程序 makeapidoc ,你可以用它來方便的產生你的API文檔,無須每次都要修改,也不用非要啟動瀏覽器來執行。
用法如下:makeapidoc -t 你的應用程序的標題 -s 源程序目錄 -d 生成文檔存放目錄
在使用之前,先修改下面2行:PHPDOC_DIR="/usr/local/lib/php/pear/PHPDoc" # windows: c:/php/pear/PHPDoc
PHPBIN="/usr/local/bin/php" #windows: c:/php/php.exe
PHPDOC_DIR是PHPDOC的目錄,PHPBIN是PHP可執行文件的路徑。
這個程序實際上是把PHP作為一個SHELLSCRIPT來使用了,不過是嵌在BASH中使用,實際上PHP完全可以做為普通的SHELL腳本一樣運行,只需加上 -q 參數,這樣就不打印HTTP HEADER了。
6. 進階:定制輸出的文檔
如果你認為缺省的PHPDOC產生的HTML文檔不夠美觀,你想做進一步的改進,比如你想把一些注釋換成中文或者是其他的文字,你想加入你的LOGO,或者是你的聯系方式,換成一個漂亮的背景圖案,有沒有方法可以作到?答案是當然可以,并且非常簡單.
PHPDOC在輸出HTML格式的API文檔的時候,使用的是PEAR的IT,ITX模塊,這是類似PHPLIB的TEMPLETE.CLASS的PEAR模塊,因此,你可以方便地定制和修改缺省的模板來為你所用.
我們先看看PHPDOC/renderer/html/templates: class.html classtree.html elementlist.html frame_packageelementlist.html
frame_packagelist.html module.html modulegroup.html packagelist.html phpdoc.css warnings.html xmlfiles.html
你會看到上面的這些文件,沒錯,這些就是PHPDOC用來產生API HTML的模板,現在你可以用你的編輯器來修改這些模板了,這里給出基本的修改原則:
7. 參考資源
作者簡介 潘凡(Night Sailer):北京賽迪數據有限公司工程師。主要從事是數據的分析和轉換,以及相關的開發工作。擅長使用VB,PERL,PHP進行開發以及Linux的中文化工作。近期興趣是Perl,Php與XML的應用,PHP的MVC開發模式,PERL-GTK的使用。您可以通過 E-mail:nightsailer@hotmail.com 跟他聯系。 |
新聞熱點
疑難解答
圖片精選