Today I needed to generate source code documentation for a webservice APIs we are in coding. One of the guys in the office suggested I take a look at Zend_Reflection. It turns out its quite simple to write PHP code to parse source files and extract the documentation from them. I took a little time to write this sample program.

This program is quite simple: it has a single class called TestClass with one method: addIntegers(). Below this class I wrote a little code which parses the file and then outputs the information. You can use this and a templating system to generate doc. I used it to write the documentation so that we can easily add it to our Wiki.

The script I wrote parses the documentation style used in Zend Framework. Here’s a sample class:

<?php

/**
 * This is a sample test class.
 *
 * This class has only one method: addIntegers() which adds
 * two integers. Its a sample class for our test.
 *
 */

class TestClass
{
    /**
     * This method adds two integers.
     *
     * This method adds the two given integers and returns
     * its sum. If only one integer is given it sums zero.
     *
     * @param int $number1  The first integer
     * @param int $number2  The second integer
     * @return int The sum of $number1 and $number2.
     *
     */

    public function addIntegers( $number1, $number2 = 0 ) {
         return $number1 + $number2;
    }
}

 

Read the rest of the post to see how to easily parse this code…

Below is the complete sample code. Fire up your text editor, copy-and-paste this code into it, save it as test_zend_reflection.php and run it. Hope this helps!

<?php

// setup Zend auto loader
require_once ‘Zend/Loader/Autoloader.php’;
$autoloader = Zend_Loader_Autoloader::getInstance();

/**
 * This is a sample test class.
 *
 * This class has only one method: addIntegers() which adds
 * two integers. Its a sample class for our test.
 *
 */

class TestClass
{
    /**
     * This method adds two integers.
     *
     * This method adds the two given integers and returns
     * its sum. If only one integer is given it sums zero.
     *
     * @param int $number1  The first integer
     * @param int $number2  The second integer
     * @return int The sum of $number1 and $number2.
     *
     */

    public function addIntegers($number1, $number2 = 0) {
         return $number1 + $number2;
    }
}

// use this file
$file = __FILE__;

// Zend Reflection require that you load the file. If you are loading
// another file then you need the following line:
// require_once( $file );
$zr = new Zend_Reflection_File( $file );

// Get all classes defined in this file and parse each one
$classDoc = array();
foreach( $zr->getClasses() as $class ) {
    $classDoc[] = parseClass( $zr, $class );
}
print_r( $classDoc );

exit(0);

// parses a Zend_Reflection_Class object
function parseClass( $zr, $class ) {   

    // read class docs
    $docBlock       = $class->getDocblock();
    $fileName       = $zr->getFileName();
    $classShortComment  = $docBlock->getShortDescription();
    $classLongComment   = $docBlock->getLongDescription();

    // load class info
    $classDoc = array(
        ‘fileName’      => $fileName,
        ‘className’     => $class->getName(),
        ’shortComment’  => $classShortComment,
        ‘longComment’   => $classLongComment,
        );

    // Read methods
    $methods = array();
    foreach ( $class->getMethods() as $methodObj ) {
        $methods[] = parseMethod( $methodObj );
    }

    $classDoc[‘methods’] = $methods;

    return $classDoc;
}   

// parses a Zend_Reflection_Method object
function parseMethod( $methodObj ) {

    $return = ‘void’;

    $docBlock  = $methodObj->getDocblock();
    $shortDesc = $docBlock->getShortDescription();
    $longDesc  = $docBlock->getLongDescription();

    // read method tags
    $tags = $docBlock->getTags();

    // parse them
    $paramDoc = array();
    foreach( $tags as $tag ) {

        if ( $tag->getName() == ‘return’ )  {
            $return     = $tag->getType();
            $returnDesc = $tag->getDescription();
        }
        if ( $tag->getName() == ‘param’ ) {
            $paramDoc[] = array(

                ‘name’ => $tag->getVariableName(),
                ‘type’ => $tag->getType(),
                ‘desc’ => trim( $tag->getDescription() ),
            );
        }

    }

    $method = array();
    $method[ ‘name’ ]       = $methodObj->getName();
    $method[ ’shortDesc’ ]  = $shortDesc;
    $method[ ‘longDesc’ ]   = $longDesc;
    $method[ ‘returnType’]  = $return;
    $method[ ‘returnDesc’]  = $returnDesc;
    $method[ ‘params’ ]     = $paramDoc;

    return $method;
}
 

If you run our PHP code you get:

$ php test_zend_reflection.php

Array
(
  [fileName] => /var/www/html/soa/doc/test_zend_reflection.php
  [className] => TestClass
  [shortComment] => This is a sample test class.
  [longComment] => This class has only one method: addIntegers() which adds
two integers. Its a sample class for our test.
  [methods] => Array
    (
      [0] => Array
        (
          [name] => addIntegers
          [shortDesc] => This method adds two integers.
          [longDesc] => This method adds the two given integers and returns
its sum. If only one integer is given it sums zero.
          [returnType] => int
          [returnDesc] => The sum of $number1 and $number2.
          [params] => Array
            (
              [0] => Array
                (
                  [name] => $number1
                  [type] => int
                  [desc] => The first integer
                )
              [1] => Array
                (
                  [name] => $number2
                  [type] => int
                  [desc] => The second integer
                )
            )
        )
    )
)
 

Leave a Reply

You must be logged in to post a
video comment.