CHAPTER 16

image

Generating Documentation with phpDocumentor

Remember that tricky bit of code? The one in which you treated that method argument as a string, unless it was an integer? Or was it a Boolean? Would you recognize it if you saw it? Maybe you tidied it up already? Coding is a messy and complex business, and it’s hard to keep track of the way your systems work and what needs doing. The problem becomes worse when you add more programmers to the project. Whether you need to signpost potential danger areas or fantastic features, documentation can help you. For a large codebase, documentation or its absence can make or break a project.

This chapter will cover:

  • The phpDocumentor application: Installing phpDocumentor and running it from the command line
  • Documentation syntax: The DocBlock comment and documentation tags
  • Documenting your code: Using DocBlock comments to provide information about classes, properties, and methods
  • Creating links in documentation: Linking to websites and to other documentation elements

Why Document?

Programmers love and loathe documentation in equal measure. When you are under pressure from deadlines, with managers or customers peering over your shoulders, documentation is often the first thing to be jettisoned. The overwhelming drive is to get results. Write elegant code, certainly (though that can be another sacrifice), but with a codebase undergoing rapid evolution, documentation can feel like a real waste of time. After all, you’ll probably have to change your classes several times in as many days. Of course, everyone agrees that it’s desirable to have good documentation. It’s just that no one wants to undermine productivity in order to make it happen.

Imagine a very large project. The codebase is enormous, consisting of very clever code written by very clever people. The team members have been working on this single project (or set of related subprojects) for over five years. They know each other well, and they understand the code absolutely. Documentation is sparse, of course. Everyone has a map of the project in their heads, and a set of unofficial coding conventions that provide clues as to what is going on in any particular area. Then the team is extended. The two new coders are given a good basic introduction to the complex architecture and thrown in. This is the point at which the true cost of undocumented code begins to tell. What would otherwise have been a few weeks of acclimatization soon becomes months. Confronted with an undocumented class, the new programmers are forced to trace the arguments to every method, track down every referenced global, check all the methods in the inheritance hierarchy. And with each trail followed, the process begins again. If, like me, you have been one of those new team members, you soon learn to love documentation.

Lack of documentation costs. It costs in time, as new team members join a project, or existing colleagues shift beyond their area of specialization. It costs in errors as coders fall into the traps that all projects set. Code that should be marked private is called, argument variables are populated with the wrong types, functionality that already exists is needlessly recreated.

Documentation is a hard habit to get into because you don’t feel the pain of neglecting it straightaway. Documentation needn’t be difficult, though, if you work at it as you code. This process can be significantly eased if you add your documentation in the source itself as you code You can then run a tool to extract the comments into neatly formatted web pages. This chapter is about just such a tool.

phpDocumentor is based on a Java tool called JavaDoc. Both systems extract special comments from source code, building sophisticated application programming interface (API) documentation from both the coder’s comments and the code constructs they find in the source.

Installation

The easiest way to install phpDocumentor is by using the PEAR command line interface.

$ pear channel-discover  pear.phpdoc.org
$ pear install phpdoc/phpdocumentor

image Note  In order to install or upgrade a PEAR package on a Unix-like system, you usually need to run the pear command as the root user.

This will make a network connection (to http://pear.phpdoc.org) and automatically either install phpDocumentor onto your system.

You can also download the package from as a phar (php archive) package from  http://phpdoc.org/phpDocumentor.phar. You can then run this directly:

$ php phpDocumentor.phar -h

Generating Documentation

It might seem odd to generate documentation before we have even written any, but phpDocumentor parses the code structures in our source code, so it can gather information about your project before you even start.

I am going to document aspects of an imaginary project called “megaquiz.” It consists of two directories, command and quiztools, which contain class files. These are also the names of packages in the project. phpDocumentor can be run as a command line tool or through a slick web GUI. I will concentrate on the command line, because it’s easy then to embed documentation updates into build tools or shell scripts. The command to invoke phpDocumentor is phpdoc. You will need to run the command with a number of arguments in order to generate documentation. Here’s an example:

$ phpdoc --directory=megaquiz/ 
    --target=docs/megaquiz/
    --title='Mega Quiz'
    --template=abstract

The --directory flag denotes the directory whose contents you intend to document (you can also use the single letter flag -d with no equals sign for its argument). --target  (or -t) denotes your target directory (the directory to which you wish to write the documentation files). Use --title to set a project title. PhpDocumentor provides a number of built-in templates that determine the look and feel of the generated documentation. You can specify the template you prefer using the --template flag. Here, I have chosen Abstract, which packs in a lot of information in a nicely compact format. You can see the available templates at http://www.phpdoc.org/templates.

Because at the time of this writing it is the most stable of the available templates, I will use the default: Clean. To get this interface I do not need to specify the --template flag at all:

$ phpdoc --directory=megaquiz/ 
    --target=docs/megaquiz/
    --title='Mega Quiz'

If we run this command on our undocumented project, we can find a surprising amount of detail. You can see the packages page of our output in Figure 16-1.

9781430260318_Fig16-01.jpg

Figure 16-1. A basic phpDocumentor output menu

As you can see, all of the classes, interfaces, and traits in the project are listed in the left-hand navigation frame, and in the main pane. The class names are all hyperlinks. In Figure 16-2, you can see some of the documentation for the Command class I created in Chapter 11.

9781430260318_Fig16-02.jpg

Figure 16-2. Default documentation for the Command class

phpDocumentor is smart enough to recognize that Command is an abstract class. Notice also that it has reported both the name and the type of the argument required by the execute() method.

Because this level of detail alone is enough to provide an easily navigable overview of a large project, it is a huge improvement over having no documentation at all. However, I can improve it significantly by adding comments to my source code

DocBlock Comments

DocBlock comments are specially formatted to be recognized by a documentation application. They take the form of standard multiline comments. Standard, that is, with the single addition of an asterisk to each line within the comment:

/**
 * My DocBlock comment
 */

phpDocumentor is designed to expect special content within DocBlocks. This content includes normal text descriptive of the element to be documented (for our purposes, a file, class, method, or property). It also includes special keywords called tags Tags are defined using the at sign (@) and may be associated with arguments. So the following DocBlock placed at the top of a class tells phpDocumentor the package to which it belongs:

/**
 * @package command
 */

If I add this comment to every class in my project (with the appropriate package name, of course), phpDocumentor may organize my classes, depending upon the template I choose.The default Clean template shows packages and namespaces at the class level, but it doesn’t expose packages to top-level navigation. The Abstract template, however, shows both namespaces and packages in navigation. Let’s regenerate documentation using Abstract:

$ phpdoc --directory=megaquiz/ 
    --target=docs/megaquiz/
    --title='Mega Quiz'
    --template=abstract

You can see phpDocumentor output that includes packages in Figure 16-3.

9781430260318_Fig16-03.jpg

Figure 16-3. Documentation output that recognizes the @package tag

In Figure 16-3, notice that the command, quizobjects and quiztools packages have been added to the navigation.

Generally, packages in documentation will mirror your directory structure. So the command package maps to a command directory. That isn’t necessary, however. A third-party developer may wish to create a Command class that is part of the command package but lives in her own directory, for example. So the @package tag makes you take responsibility for associating classes with packages, but it also affords you flexibility that would not be available by using the file system to guess at package names.

Documenting Classes

Let’s add some more tags and text that are useful in class- or file-level DocBlocks. I should identify the class, explain its uses, and add authorship and copyright information.

Here is the Command class in its entirety:

/**
 * Defines core functionality for commands.
 * Command classes perform specific tasks in a system via
 * the execute() method
 *
 * @package command
 * @author  Clarrie Grundie
 * @copyright 2013 Ambridge Technologies Ltd
 */
abstract class Command {
    abstract function execute( CommandContext $context );
}

The DocBlock comment has grown significantly. The first sentence is a one-line summary. This is emphasized in the output and extracted for use in overview listings. The subsequent lines of text contain more detailed description. It is here that you can provide detailed usage information for the programmers who come after you. As we will see, this section can contain links to other elements in the project and fragments of code in addition to descriptive text. I also include @author and @copyright tags which should be self-explanatory. You can see the effect of my extended class comment in Figure 16-4.

9781430260318_Fig16-04.jpg

Figure 16-4. Class details in documentation output

Notice that I didn’t need to tell phpDocumentor that the Command class is abstract. This confirms something that we already know, that phpDocmentor interrogates the classes with which it works even without our help. But it is also important to see that DocBlocks are contextual. phpDocumentor understands that we are documenting a class in the previous listing, because the DocBlock it encounters immediately precedes a class declaration.

File-Level Documentation

Although I tend to think in terms of classes rather than of the files that contain them, a file level comment can be a good place to insert copyright and license information A file comment should be the first DocBlock in a document. It should contain a @package tag and it should not directly precede a coding construct. In other words, if you add a file-level DocBlock, you should ensure that you also add a class-level comment before the first class declaration.

Many open source projects require that every file includes a license notice or a link to one. Page-level DocBlock comments can be used, therefore, for including license information that you do not want to repeat on a class-by-class basis. You can use the @license tag for this. @license should be followed by a URL, pointing to a license document and a description:

/**
 * @license http://www.example.com/lic.html Borsetshire Open License
 */

Documenting Properties

All properties are mixed in PHP. That is, a property can potentially contain a value of any type. There may be some situations in which you require this flexibility, but most of the time, you think of a property as containing a particular data type. phpDocmentor allows you to document this fact using the @var tag.

Here are some properties documented in the CommandContext class:

class CommandContext {
/**
 * The application name.
 * Used by various clients for error messages, etc.
 * @var string
 */
    public $applicationName;
 
/**
 * Encapsulated Keys/values.
 * This class is essentially a wrapper for this array
 * @var array
 */
    private $params = array();
 
/**
 * An error message.
 * @var string
 */
    private $error = "";
// ...

As you can see, I provide a summary sentence for each property with fuller information for the first two. I use the @var tag to define each property’s type. You can see the documented properties in Figure 16-5.

9781430260318_Fig16-05.jpg

Figure 16-5. Documenting properties

Documenting Methods

Together with classes, methods lie at the heart of a documentation project. At the very least, readers need to understand the arguments to a method, the operation performed, and its return value.

As with class-level DocBlock comments, method documentation should consist of two blocks of text: a one-line summary and an optional description. You can provide information about each argument to the method with the @param tag. Each @param tag should begin a new line and should be followed by the argument name, its type, and a short description.

Because PHP does not constrain return types, it is particularly important to document the value a method returns You can do this with the @return tag. @return should begin a new line and should be followed by the return value’s type and a short description. I put these elements together here:

/**
 * Perform the key operation encapsulated by the class.
 * Command classes encapsulate a single operation. They
 * are easy to add to and remove from a project, can be
 * stored after instantiation and execute() invoked at
 * leisure.
 * @param  $context CommandContext Shared contextual data
 * @return bool     false on failure, true on success
 */
    abstract function execute( CommandContext $context );

It may seem strange to add more documentation than code to a document. Documentation in abstract classes is particularly important, though, because it provides directions for developers who need to understand how to extend the class. If you are worried about the amount of dead space the PHP engine must parse and discard for a well-documented project, it is a relatively trivial matter to add code to your build tools to strip out comments on installation. You can see our documentation’s output in Figure 16-6.

9781430260318_Fig16-06.jpg

Figure 16-6. Documenting methods

Namespace support

As you have seen, prior to PHP 5.3 you had to divide a project into logical chunks using file naming schemes and the @package tag. Now, of course you can organize software components into namespaces. As you might expect, phpDocumentor captures and documents the namespaces you use in a project.

Let’s migrate megaquiz so that it uses namespaces. Here is the new Command class, stripped of documentation so that you can more easily see the use of namespaces:

namespace megaquizcommand;
 
abstract class Command {
    abstract function execute( megaquizcommandCommandContext $context );
}

In Figure 16-7, you can see the namespace hierarchy in place.

9781430260318_Fig16-07.jpg

Figure 16-7. Namespaces documented

Creating Links in Documentation

phpDocumentor generates a hyperlinked documentation environment for you. Sometimes, though, you will want to generate your own hyperlinks, either to other elements within documentation or to external sites. In this section, we will look at the tags for both of these.

As you construct a DocBlock comment, you may want to talk about a related class, property, or method. To make it easy for the user to navigate to this feature, you can use the @see tag @see requires a reference to an element in the following format:

class
class::method()

or like this:

class::$property

This reference should be followed by some label text. So in the following DocBlock comment, I document the CommandContext object and emphasize the fact that it is commonly used in the Command::execute() method:

namespace megaquizcommand;
 
/**
 * Encapsulates data for passing to, from and between Commands.
 * Commands require disparate data according to context. The
 * CommandContext object is passed to the Command::execute()
 * method and contains data in key/value format. The class
 * automatically extracts the contents of the $_REQUEST
 * superglobal.
 *
 
 * @author  Clarrie Grundie
 * @copyright 2013 Ambridge Technologies Ltd
 * @see megaquizcommandCommand::execute()   the execute() method
 */
 
class CommandContext {
// ...

image Note  At the time of this writing, the @see, and @link tags are partially implemented. Although links are generated, they do not yet point anywhere. This should be fixed in a forthcoming release of phpDocumentor.

As you can see in Figure 16-8, the @see tag resolves to a link. Clicking this will lead you to the execute() method.

9781430260318_Fig16-08.jpg

Figure 16-8. Creating a link with the @see tag

image Note  Previous editions of phpDocumentor supported @see tags embedded within text using the syntax {@see class::method()}. This support has been discontinued, although I have been told unofficially that it may be reinstated in future versions.

You can also create web links using the @link tag. Simply combine the @link tag with a URL:

@link http://www.example.com More info

Once again, the URL is the target, and the description that follows it is the clickable text.

You may want to make a reciprocal link. Command uses CommandContext objects, so I can create a link from Command::execute() to the CommandContext class and a reciprocal link in the opposite direction. I could, of course, do this with two @see tags. @uses handles it all with a single tag, however:

/**
 * Perform the key operation encapsulated by the class.
 * ...
 * @param  $context  Shared contextual data
 * @return bool     false on failure, true on success
 * @link http://www.example.com   More info
 * @uses megaquizcommandCommandContext
 */
    abstract function execute( CommandContext $context );

When it encounters the @uses tag, phpDocumentor should create a link in the Command::execute() documentation: “Uses: CommandContext”. In the CommandContext class documentation, a new link should appear: “Used by: Command::execute()”.

image Note  At the time of this writing, @uses is not fully implemented. This is a known issue and should be fixed in a forthcoming phpDocumentor release.

You can see the @link and @uses tags rendered in Figure 16-9.

9781430260318_Fig16-09.jpg

Figure 16-9. Documentation including @link and @uses tags

Summary

In this chapter, I covered the core features of phpDocumentor. You encountered the DocBlock comment syntax and the tags that can be used with it. I looked at approaches to documenting classes, properties, and methods, and you were provided with enough material to transform your documentation, and thus improve collaborative working immeasurably (especially when used in conjunction with build tools and version control). There is a lot more to this application than I have space to cover, though, so be sure to check the phpDocumentor homepage at http://www.phpdoc.org.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.43.134