Sei sulla pagina 1di 12

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

MENU

(http://www.sitepoint.com/author/bskvorc/)
Bruno Skvorc (http://www.sitepoint.com/author/bskvorc/)

Published August 1, 2012


Tweet (Https://twitter.com/share?text=Generate+Documentation+with+ApiGen&via=sitepointdotcom)

Subscribe (Https://confirmsubscription.com/h/y/1FD5B523FA48AA2B)

If youve ever worked with someone elses code, you know the pain (or pleasure) of missing (or
existing) documentation. Well documented code is one of the cornerstones of professional software
development, and unless you learn how to document your code so that it becomes second nature,
youre doing yourself and others more harm than good.
If this sounds overly discouraging, its because it should be. If youre writing undocumented code, you
should stop this very moment. Im serious. Drop everything, save and quit, and focus on improving this
essential part of your workflow.
Over the years, Ive had to suffer through horrible documentation (hello, Zend Framework!) and have
glided through some pretty solid stuff as well (thank you, Swift Mailer!). I try to document every single
file I produce, and Ive been doing it long enough now that it has become second nature. I have a strict
documentation standard I follow, one that is compatible with ApiGen, the documentation generator,
and one that is highly human-readable but also fully compatible with modern IDEs. This means I can
generate my library documentation for the public along with examples, tutorials, descriptions and
possible errors with a single command.
ApiGen is a docblock parser like PhpDocumentor. PhpDocumentor has been around for much longer
than ApiGen, but unfortunately its development is somewhat stunted and it lacks in terms of modern
documentation and examples. It also has some unpleasant dependencies which can cause problems
on fresh PHP installations, and often throws errors that arent documented anywhere. You can find out
1 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

more about the PhpDocumentor in a previous SitePoint article (http://www.sitepoint.com/introductionto-phpdoc/). As for which is better I believe ApiGen to be the logical choice due to the following
downsides of PhpDocumentor:
requires page-level docblocks (above namespaces) that serve no purpose; they are never properly
parsed and the entered descriptions are nowhere to be found. Update, August 24th 2012: a
commenter has pointed out that page-level blocks are in fact used in templates other than the
default. They are still, however, not essential, and generate errors when PhpDoc is parsing, staying
in the documentation as logged errors indefinitely.
no search in the generated documentation.
layout errors long package names break the Api Documentation drop-down menu, the
generated GraphViz charts will have a Z-index higher than the menus and will thus appear above
them even when the menus are expanded (see note below)
fails to recognize some type hinting for unknown reasons. (this is fixed in alpha8, see note below)
no html support in tag descriptions HTML tags stay visible, so advanced formatting is not
possible from what Ive noticed. (see note below)
Note, Aug. 24th: Most of these issues have been fixed in the last version I tested alpha 10. However,
the lack of a search function is still a deal breaker for me.

Well be using a couple classes I wrote for the purpose of this tutorial spread out across a couple
folders under two simple namespaces. These classes wont be a whole lot of use in the real world, but
theyll serve us well for this article. Since the classes are rather large with all the comments and
spacing dictated by the PSR-2 standard, Ive uploaded the full code (https://github.com
/phpmasterdotcom/GenerateDocumentationWithApiGen) to GitHub. There are multiple branches
available in the repo; the first branch base-code contains nothing but the actual classes, The second
branch commented-code contains fully commented code, and the third branch documentationgenerated has a docs directory in which you can find auto-generated documentation.
Observing every class would take too much time and space, so instead lets focus on just one right
now. Well take a look part by part at the User class and Ill explain the docblocks for each snippet:

2 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

3 sur 12

http://www.sitepoint.com/generate-documentation-with-apigen/

<?php

/**

*Thisblockcontainsashortdescriptionoftheclasses

*presentintherestofthisfile.

*Thisparagraphcontainsthelongdescriptionofthesame

*things.

*ThisentireblockwillbecompletelyignoredbyApiGenand

10

*ishereonlytomaintaincompatibilitywithPhpDocumentor.

11

*Requiringthepresenceofthisnearuselessblockinevery

12

*phpfileisoneofPhpDocumentorsdownsides.

13

14

*@packageSomepackagethatonlyPhpDocumentorsees.

15

*/

16

namespaceMyLibrary;

17

18

useMyLibraryAbstractsSuperType;

19

useMyLibraryInterfacesUserMapper;

20

useMyLibraryExceptionsUserasUserException;

21

22

/**

23

*TheUserclassisasampleclassthatholdsasingle

24

*userinstance.

25

26

*TheconstructoroftheUserclasstakesaDataMapperwhich

27

*handlestheuserpersistenceinthedatabase.Inthiscase,

28

*wewillprovideafakeone.

29

30

*@categoryMyLibrary

31

*@packageMain

32

*@licensehttp://www.opensource.org/licenses/BSD3Clause(http://www.opensource.org/licenses/BSD3

33

*@example../index.php

34

*@example<br/>

35

*$oUser=newMyLibraryUser(newMappersUserMapper());<br/>

36

*$oUser>setUsername('swader');<br/>

37

*$aAllEmails=$oUser>getEmails();<br/>

38

*$oUser>addEmail('test@test.com');<br/>

39

*@version0.01

40

*@since20120707

41

*@authorBrunoSkvorc<bruno@skvorc.me>

42

*/

43

classUserextendsSuperType

44

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

As what should be common practice for everyone by now, we first define a namespace at the
beginning of the class file (ignore the entire docblock before the namespace which is there only for
PhpDocumentor compatibility). We then follow it up with some use statements in order to establish
aliases for the classes used by the class.
Next, we see a comment block immediately preceding the class declaration. This is a class description
and it tells the user/developer what the class does in a short and concise TL;DR manner. The main
class description usually consists of two parts the short description and the long description. The
short description is the first paragraph, and the long description is everything from the short
description to the first docblock marker (even multiple paragraphs, in-line examples, anything the
author thinks of).
What follows then are several markers, each with its own purpose.
@category specifies the category to which the class belongs. Categories are parents to packages

(see below) and form large supersets of classes and utilities. Categories are usually as encompassing
as namespaces, and as such our @category is actually the name of our namespace.
@package defines a smaller, more precise set of classes and utilities. Its usually a subdirectory in

the main namespace, or in the case of our User class, the Main package, which means its at the root
of our library. There is also the @subpackage marker which can go even deeper. There is usually no
need for it (due to namespaces handling all tree structures nicely), but an example would be
@category MyLibrary, @package User @subpackage Exceptions, which means the class is in the
MyLibrary category, and is a User-related Exception inside the User package.
@category and @package are arbitrary, and many developers use them as they see fit. There is no

specific standard because properly namespaced code replaces the need for them namespaces take
precedence over these markers. Some developers even like to mark their classes as @category
controller, @category view, and @category model in MVC libraries. When namespaces are not
used, parsers like ApiGen will look at categories and packages to organize your documentation but
they prefer to ignore them in favor of namespaces.
@license specifies the license that applies to the code, and is usually a link to an online resource.

Another useful marker can be the @copyright marker, which tells users if the code is copyrighted.
The copyright marker usually contains the year range and the entity which copyrighted the code, be it
an individual or a legal entity.
@example is a path to a file containing sample usage of the class this marker is in. In our case, we

indicate that sample usage of the User class can be found one directory up, in the index.php file.
The @example marker can also provide another in-line example. A class can have as many example
tags as it needs.
@version is the version tag and should be changed with every update.

4 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

@since marks the date of creation for the current class.


@author specifies the developer who created the class. It can be just a name, or an e-mail address

formatted as Name . A docblock can contain multiple authors and all will be listed in the
documentation.
Continuing onward, lets look at the properties of the class right under the class declaration:

/**

*Theuser'susername.Defaultstocontactemail.

*@varstring

*/

protected$sUsername;

/**

*Anarrayoftheuser'semails.Thefirstelement

*isthemaincontactemail.

10

*@vararray|null

11

*/

12

protected$aEmails=null;

13

14

/**

15

*Abooleanflagonwhetherornottheuserisloggedin

16

*@varbool

17

*/

18

protected$bLoggedIn=false;

19

20

/**

21

*Themapperisresponsibleforalldatapersistenceandfor

22

*fetchingexistingrecordsfromthedatabasewhenausername

23

*isprovided.

24

*@varUserMapper

25

*/

26

protected$oMapper=null;

Property docblocks only need to contain a short description and a @var marker which hints at the
value type the property will contain. If there is a chance of multiple types being contained in said
property, a pipe separator can be used, meaning or (e.g. array|null).
Finally, lets have a look at the documentation of a method, in this case, the setUsername()
method:

5 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

/**

*Setstheusernameforthegivenuserinstance.Iftheusername

*isalreadyset,itwillbeoverwritten.Throwsaninvalid

*argumentexceptioniftheprovidedusernameisofaninvalid

*format.

*@paramstring$sUsernameTheusernamestringtoset

*@returnUser

10

*@throwsInvalidArgumentException

11

*@todoChecktomakesuretheusernameisn'talreadytaken

12

13

*@since20120707

14

*@authorBrunoSkvorc<bruno@skvorc.me>

15

16

*@edit20120708<br/>

17

*JohnDoe<john@doe.com><br/>

18

*Changedsomeessential

19

*functionalityforthebetter<br/>

20

*#edit3392

21

*/

22

publicfunctionsetUsername($sUsername)

23

24

if(!$this>checkString($sUsername,5)){

25

thrownewInvalidArgumentException(

26

"Theusernameneedstobeavalidnonemptystringof5charactersormore."

27

);

28

29

30

$this>populate($this>oMapper>findByUnique($sUsername));

31

$this>sUsername=$sUsername;

32

33

return$this;

34

Method docblocks always start with the description of the method which should be as detailed as
possible in order to avoid any and all problems when other developers use it.
A list of accepted parameters follow the description using one or more @param markers. Each marker
should have an expected type (string, bool, int, etc. or a mix of several types separated with the pipe
character array|int|string), the actual parameter name as it appears in the method declaration, and its
description.
@return describes the return value of the method. If the method returns no value, the marker
6 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

should say @return void, otherwise, a specific type should be declared (e.g. @return int, or in our
case @return User since the method returns the instance of the very object it was executed on). A
description of the data is optional but desired when return values can get complicated (e.g. associative
arrays).
The @throws marker lets the developer know which Exceptions to expect in cases of errors. There
can be multiple @throws markers, and they can (but usually dont) have descriptions. Instead, the
situation in which an exception is thrown is usually described in the method description.
If a method/class is unfinished and some functionality is still to be added, the @todo marker can be
utilized. Not only is it recognized by ApiGen and turned into a task list when the documentation is
being generated, it also shows up on the task list in many modern IDEs enabling you to easily track
unfinished work. Docblocks can have as many todo markers as they want they can even be added
in-line (in the middle of a method) and will still be recognized by ApiGen and added to the task list.
Using @since and @author at the method-level is not very common since putting the author and
date into the class-level docblock is usually sufficient, but knowing which developer added a
mysterious method into a class that was originally yours is invaluable in large teams in which multiple
developers sometimes work on the same class. This is entirely optional and takes a bit more time and
keystrokes, but Ive found that the benefits far outweigh the effort in large projects.
The @edit tag is not an officially supported tag. It has no meaning or value in the official docblock
documentation and is not expected by any documentation generator I know of. Ive enforced its usage
simply because its indispensable in following code changes through means other than version
control. In tandem with Git or SVN, the @edit tag can easily let you know who edited which file,
when and why and the hashtag at the end will be the same hashtag used in the commit message of
the edit in the actual version control system, so it can be easily found when needed. Proper version
control and teamwork is outside the scope of this article, but you would do well to adopt the @edit
marker when working on other peoples code the clarity it provides when you look back on your edits
months down the road can save you countless hours of frustration.
By having this kind of documentation in place, we make sure that every developer who opens our files
in the future knows exactly what each class does, and has good autocomplete regardless of which IDE
they use. Now lets turn our documentation into something even prettier to look at!

Installing ApiGen is as simple as their website says. To install ApiGen, run the following commands
(you might have to sudo them):

7 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

$pearconfigsetauto_discover1
$pearinstallpear.apigen.org/apigen

Thats it, ApiGen is now installed. If this doesnt work, try following some of the alternative instructions
(http://apigen.org/##installation) as detailed on their website.
Now its time to run ApiGen with some useful flags (everything except source and destination is
optional):

$apigensource.destinationdocs/apigentodoyes
title"MyLibraryDocumentation"phpnodownloadyes

The destination flag instructs ApiGen to place the documentation in the docs/apigen
directory. The todo flag generates a task list from any @todo markers it finds. title sets
the title of the documentation project, the php flag tells ApiGen to ignore core PHP files (like
certain exceptions, if used) and the download flag tells it to generate a downloadable ZIP archive
of our source code as well.
Look at the generated documentation by opening index.html in the documentations folder, or by
visiting the appropriate virtual host URL in your browser. What ApiGen generated there is an
impressive set of HTML files which, when used together, form a beautiful static website with your
projects entire structure laid out. You can navigate through namespaces, subfolders, even use a
search function with a fast auto-complete in the top right corner and download the entire zipped
source. Every property, method and class we defined in the project is now visible in structured tabular
and/or tree form on screen even todo comments (click on todo at the top of the screen)!
All you have to do in order to expose this documentation to the public is upload it to your server and
point a domain or subdomain at it everything you see in the HTML files will also be visible to the
visitors.
ApiGen has a plethora of other useful flags (implementation of Google Analytics, a custom root URL, a
custom configuration directive, styling, etc.) but these are outside the scope of this article and might
be covered in a later article into greater detail.

Whether youre a single developer working on smaller projects, or part of a larger team working on a
joint effort, commenting is essential to your workflow. If done properly and with certain project-wide or
8 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

team-wide standards in mind, it will help you and your colleagues avoid hours of toiling later on when
revisiting older code and will allow users of your code to have a much smoother experience getting into
it and sticking around. Bad documentation is one of the main reasons new users of complex libraries
give up on them so to avoid turning your users and colleagues away, adopt these best practices
today.
Image via Fotolia (http://us.fotolia.com/?utm_source=sitepoint&utm_medium=website_link&utm=campaign=sitepoint)

(http://www.sitepoint.com/author/bskvorc/)

Bruno Skvorc (http://www.sitepoint.com/author/bskvorc/)


Bruno (https://plus.google.com/u/0/104771776404197897488?rel=author) is a coder from Croatia with
Masters Degrees in Computer Science and English Language and Literature. Hes the editor of
SitePoints PHP channel and a developer evangelist for Diffbot.com (http://diffbot.com). He avoids
legacy code like the plague and when picking projects makes sure theyre as cutting edge as possible.
Hes a treadmill desk enthusiast (https://4kk.me) and active (board)gamer who sometimes blogs
(http://bitfalls.com).

(https://twitter.com/bitfalls)

(http://www.github.com/swader)

(http://linkedin.bitfalls.com)
(https://plus.google.com/+BrunoSkvorc?rel=author)

9 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

Get a free 32-page chapter of JavaScript: Novice to Ninja and receive updates on exclusive offers
from SitePoint.

Claim Now

10 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

Comments for this thread are now closed.

11 Comments

Attila Fulop

At first run after install I had `ERROR: the server encountered an internal error and was unable to
complete your request.` error message. Neither --debug did help. I had to set date.timezone in php.ini
as described here: https://github.com/apigen/apig...
I hope this might help others as well.

Bruno Skvorc

Thanks for the heads up!

Kris

There's an error in your install directions. You have:


pear install pear.apigen.org/api
it should be:
pear install pear.apigen.org/apigen

Bruno Skvorc

Thank you, not sure how I missed that!

Timothy Boronczyk

Thanks for the catch! I've fixed it in the article.

boen_robot

About the part


"requires page-level docblocks (above namespaces) that serve no purpose; they are never properly
parsed and the entered descriptions are nowhere to be found."
File descriptions actually do serve a purpose - they are shown under a "Files" menu that's present in
pretty much all templates... admittedly other than the default one.

Bruno Skvorc

Didn't know this, never changed PhpDoc templates, thanks for the heads up!

Mike van Riel

The given list of downsides appears to be composed of a few bugs and a few misunderstandings
maybe?
>> requires page-level docblocks (above namespaces) that serve no purpose; they are never
properly parsed and the entered descriptions are nowhere to be found.
11 sur 12

18/03/2015 18:49

phpmaster | Generate Documentation with ApiGen

http://www.sitepoint.com/generate-documentation-with-apigen/

About
About us (/about-us/)
Advertise (/advertising)
Press Room (/press)
Legals (/legals)
Feedback (mailto:feedback@sitepoint.com)
Write for Us (/write-for-us)

Our Sites
Learnable (https://learnable.com)
Reference (http://reference.sitepoint.com)
Web Foundations (/web-foundations/)

Connect

2000 2015 SitePoint Pty. Ltd.

12 sur 12

18/03/2015 18:49

Potrebbero piacerti anche