注册 | 登录
收藏 | 帮助
热门文章
编辑推荐
相关文章  
用WinRAR解析木马病毒的捆绑原理
识破用WinRAR捆绑的木马
另类:用Ftype巧妙清除病毒
浅谈除不尽理还乱的Spyware间谍软
Microsoft AntiSpyware微软出品的
DNS 系统设定例--8.[Rev] 特殊网
DNS 系统设定例--9.[Rev] 特殊网
DNS 系统设定例--10.[Rev] 特殊网
DNS 系统设定例--14.[Rev] NCTU 
DNS 系统设定例--15.[Rev] NCTU 
您现在的位置: 顶尖设计 >> IT学院 >> 编程开发 >> PHP >> 文章正文
PEAR:使用PHPDoc轻松建立你的PEAR文档
作者:潘凡  来源:IBM中国  点击:  更新:2006-12-19
简介:

对于一个开发人员,文档总是最感到头疼的事情之一。而且,很可能你对待文档会采取截然不同的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的工作原理:

  1. phpdoc扫描指定目录下面的php源代码,扫描其中的关键字,截取需要分析的注释,然后分析注释中的专用的tag,生成xml文件,接着根据已经分析完的类和模块的信息,建立相应的索引,生成xml文件
  2. 对于生成的xml文件,使用定制的模板输出为html文件。

从设计上来说,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节的说明)前面。下面是一个文档注释的例子:



/**

 * Common base class of all phpdoc classes (简述,用在索引列表中)

 *

 * As a kind of common base class PhpdocObject holds

 * configuration values (e.g. error handling) and debugging

 * methods (e.g. introspection()). It does not have a constructor,

 * so you can always inheritig Phpdoc classes from this

 * class without any trouble. (详细的功能描述)

 *

 * @author   Ulf Wendel 

 * @version  $Id: PhpdocObject.php,v 1.3 2001/02/18 15:29:29 uw Exp $

 * @package  PHPDoc (文档标记)

 */

class PhpdocObject {

    .....

}

以上的文档注释将会生成如下的文档:



<b>PhpdocObject</b>



PhpdocObject



Common base class of all phpdoc classes





<b>private class PhpdocObject </b>



Common base class of all phpdoc classes

As a kind of common base class PhpdocObject holdsconfiguration values (e.g. error

handling) and debuggingmethods (e.g. introspection()). It does not have a

constructor,so you can always inheritig Phpdoc classes from 
thisclass without any trouble. Authors Ulf Wendel <ulf.wendel@phpdoc.de> Version $Id: PhpdocObject.php,v 1.3 2001/02/18 15:29:29 uw Exp $

3.2 非文档性注释
如果你的注释没有放在那些phpdoc指定的关键字前面,那么phpdoc认为你所作的这些注释是属于非文档注释,将不会被phpdoc所分析,也不会出现在你产生的api文当中。

3.3 如何书写你的文档性注释
从3.1 我们可以看到,一个文档性的注释,是由3个部分组成的,分别是:功能简述区,功能详细说明区,文档标记区。

首先,第一行是一个注释开始的标志"/**",然后是回车,从第2行开始就是功能简述区,功能简述区是以缩进的"*"开始的,在简述的正文和这个"*"号之间用空格分隔(注意,在文档中,都是以*开始,并且这些*保持对齐的缩进格式)。功能简述的正文一般是简明扼要地说明这个类,方法或者函数的功能,功能简述的正文在生成的文档中将显示在索引区。

在功能简述区后面是一个空的注释行,用来分割简述区和详细说明区。功能详细说明区也是以缩进的'*"来引导的,这部分主要是详细说明你的API的功能,用途,如果可能,也可以有用法举例等等。在这部分,你应该着重阐明你的API函数或者方法的通常的用途,用法,并且指明是否是跨平台的(如果涉及到),对于和平台相关的信息,你要和那些通用的信息区别对待,通常的做法是另起一行,然后写出在某个特定平台上的注意事项或者是特别的信息,这些信息应该足够,以便你的读者能够编写相应的测试信息,比如边界条件,参数范围,断点等等。

在功能详细说明区后面,是空白的注释行,然后是文档标记区,你可以在这些书写相关的文档标记(这些文档标记的用法请参考后面的第4节),指明一些技术上的细节信息,最主要的是调用参数类型,返回值极其类型,继承关系,相关方法/函数等等。多个文档标记应该使用相同的缩进,组成一个"标记块",便于阅读和分析。

在文档标记区下面的一行就是注释结束行"*/",注意,在注释结束标记*/后面应该直接跟一个回车,不要另外附加其他的东西,否则可能造成PHPDOC分析出错。

以上就是书写一个文档性注释的基本方法,下面我们讨论一下书写文档时的规范和技巧。

3.4 文档书写指南
在你描述你的代码的用途或者是功能的时候,最好能够遵循大多数人的习惯,通俗地讲就是"你告诉我的信息正是我想要知道的"。为此,这里将介绍一些书写文档注释的技巧和规范,希望能够对你有所帮助:

  1. 使用 <code> 来标志关键字和命名及相关的代码。如果在文档中需要引用一些关键字,变量名,或者是你要给出一些代码的例子,那么你最好使用<code></code>来将这些关键字,变量名,代码片段和你的文档分隔开,这样,读者阅读的时候,将会知道,这些将是运行的代码,关键字而不是你的描述性的语言。
  2. 使用简单,明确的语言,避免冗长,复杂,晦涩的长句来描述。尤其是在功能简述,参数说明等索引部分中,尽量使用简单明白的语言揭示主要的信息,把其他的细节放在详细说明部分去阐述。如果你使用英语,建议使用短语而不一定是句子。
  3. 如果使用英语,建议使用第3人称单数的形式来说明
  4. 在给方法,函数说明的时候,你需要说明的是这个方法"作了什么",而不是"怎么做"。因此,建议你的说明是以动词开始,比如"返回记录数","删除给定的记录"等等。
  5. 当你引用的某个对象或者变量是从当前的类中建立的,那么使用 "this" 代替 "the" 来指代那个对象或者是变量
  6. 避免空话,废话,对于你所要给出的API,在你的API后面要有它的功能描述,是其能够"自成文档"。所谓的空话,废话是指,你的描述不是功能描述,而只是API名称的简单重复和罗列,或者是用另一个API来解释这个API,到头来,你的读者也不知道你所要表达的内容实质。你的描述,应该是那些从你的类名,方法名,或者是函数名看不到的补充的信息,而不是把你的API名称再重复一遍。很多人可能很多人(包括我)不知不觉中就犯了这个错误,下面是一个例子:
    
    
    	/**
    
         * 设置用户记录集
    
         *
    
         * @param text  给定的表名
    
         */
    
        function set_user_record($table) {
    
    

你从上面这段注释中能够知道什么?因此,这段注释实际上是废话,因为你从函数名称上是可以看出的,下面是改进后的:



	/**

     * 打开系统用户表并设置为当前用户记录集,此记录集将用于随后相关用户数据更新操作的缺省记录集。
如果失败则抛出一个数据库错误。 * * @param text 要打开的系统用户表的表名。 */ function set_user_record($table) {

  • 适当地使用链接。为你文档中引用的API名称(包括你的其他类及方法,PHP的函数等)添加适当的链接是很受欢迎的:你可以使用@link标记来添加到相关的API的链接,不过,你没有必要为文档中引用的所有的API都添加连接,这样会很不美观,这里有一个简单的标准:如果用户在这个地方看到某个API,确实希望要去点击以便获取更多信息,这样有助于他们去理解你的文档,并且即使添加了链接,只在它第一出现的是时候添加,没有必要重复添加相同的LINK。
  • 由于PHPDOC的功能限制,一个PHP文件只定义一个类或模块,不要把类和模块的定义放在同一个文件里,否则PHPDOC可能无法工作,至少目前版本是这样。如果你的框架使用OOP来构建,应避免同时使用模块或模块组;同时应该仔细规划你的应用结构,你的应用框架应该是一个类似树型的结构,顶层的分支不要太多,例如你可以设计2个超类,分别是作为正常应用和错误处理的超类,其余的都从这2个类派生出来。

    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() {
    
        ;
    
      }
    
    }
    
    
    @access (public|private) 使用范围:class, function, var, define, module

    指明这个变量、类、函数/方法的存取权限。如果你的函数是内部使用,你应该指明它为private,这样的好处是,即使PHP不能阻止其他的人使用你的私有数据,但是至少你向你的用户传达这样的信息,这是一个私有的函数,因此不保证在将来的版本中仍存在;对于使用者而言,表示为@private的数据和方法,你不应该直接使用,即使你可以这样做。

    举例:

    
    
    /**
    
    * 这是一个绘五星图案的抽象类.
    
    * @abstract
    
    * @access    public
    
    */
    
    class paint_start {
    
      
    
      /**
    
      * 绘制数量
    
      * @abstract
    
      * @access    private
    
      */
    
      var $number;
    
    	
    
      /**
    
      * 绘制五星图案
    
      * @abstract
    
      * @access    public
    
      */
    
      function paint() {
    
        ;
    
      }
    
    	
    
    }
    
    
    @author Name [<email>] [, ...] 使用范围:class, function, var, define, module, use

    指明作者信息,依次是作者姓名,email地址,其他的通讯信息。如果有多个作者,按照其先后次序,使用多个@author依次列出:

    • * @author Night Sailer <night@hotmail.com>
    • * @author Lee Tester <tester@gnome.org>
    @brother (function()|$variable) 使用范围:class, function, var, define, module, use
    @sister (function()|$variable) 使用范围:class, function, var, define, module, use

    指出兄弟类、函数或者是变量.这些函数、类、变量等有相似的信息和并实现相同的功能。比如,调用和返回的参数的个数和类型相同,实现的功能也一样。这种情况,你可以使用@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 descri

    [1] [2] 下一页






  • 上一篇文章:
  • 下一篇文章:
  • 分享此文:该页面添加到 Mister Wong 添加到雅虎Yahoo!收藏 Add to:Del.icio.us Post to Furl Digg this 添加到Google书签 reddit spurl blogmarks 365Key 评论  收藏  分享  打印
     我来说两句
    姓名:       验证码:   
    主页: 
    评分: 1分 2分 3分 4分 5分
    本频道近期热评文章:
      关于我们 | 联系我们 | 站点地图 | 广告投放 | 友情链接 | 在线留言 | 版权申明
    版权所有 © 2004-2007 顶尖设计(bobd.cn)
    未经授权禁止转载,摘编,复制本站内容或建立镜像. 沪ICP备07504942号 
    网络110
    报警服务