
Documentation comes in many shapes and forms. In this post, I'll demonstrate how to autogenerate internal and external interface technical documentation for engineers and stakeholders alike in your PHP projects. If you're not in the PHP ecosystem, fear not - there exists similar tooling for your ecosystem so read ahead to know what to look for!
Internal Interface Schema
Think back to the last time you searched for that method which you just can't seem to remember its usage, return types/values, or parameter requirements - it's more than likely you visited the language or frameworks vendor documentation for this. For example, if you're in the Java world you'll be familiar with docs.oracle, or in the .NET world, you'll have no doubt seen the MSDN reference pages such as class method pages.

Example ApiGen autogenerated documentation (Source: Oracle NetBeans)
As it turns out, producing this type of documentation is both easy and hugely valuable for yourself and your team. So how do we produce it? All that's required is to follow the phpdoc conventions for classes and methods using the standard docblock tags. For example, this might resemble the below snippet from the php-fig standards. Sometimes, various editors and IDEs support the generation of such docblocks for convenience and structural integrity. For example, JetBrains PHPStorm and Microsoft Visual Studio Code extensions.
/**
* This is a Summary.
*
* This is a Description. It may span multiple lines
* or contain 'code' examples using the _Markdown_ markup
* language.
*
* @see Markdown
*
* @param int $parameter1 A parameter description.
* @param \Exception $e Another parameter description.
*
* @\Doctrine\Orm\Mapper\Entity()
*
* @author Your Name
* @return string
*/
First things first, let's not reinvent the wheel, so it's time to find a package that can do this for us. The one we'll explore is apigen(packagist) as this is one of the easiest doc generators I've worked with thus far. Unless you're feeling adventurous and wish to install from source, the easiest method of installing is via PHPs popular package manager, composer. Installation of which is painless - visit the installation documentation and download the easy-install tool for your platform either globally, or locally. Follow their instructions and once installed, believe it or not, the hard bit is over.
Now we'll install the apigen package itself into our project. Navigate to your project and if you've not already initialised your project with composer, issue the init command and fill out the details it asks for to generate the composer.json schema file which will track the packages and associated versions required for by your project. For more information on this, head over to composer's basic usage documentation. To install apigen, issue one of the following commands based on whether you installed globally or locally.
Global:
php path/to/composer.phar install apigen/apigen
Local:
composer install apigen/apigen
Alternatively, if you manually add the apigen entry to your composer.json file, issue the update command instead.
composer update [apigen/apigen]
It's worth noting at this point an issue I ran into relating to the PHP compatibility of its releases. As the apigen page on packagist indicates, all versions above 4.1.2 require PHP 7.1 or higher. Thus, if you are pre-7.1, edit the auto-included composer.json entry for apigen to "apigen/apigen": "^4.1.2" and re-run composer update.
Configuration
Once installed, we need to create ./apigen.yml in the root of the project. An example default configuration is located in the README, but is also below for convenience.
parameters:
visibility\_levels: \[public, protected, private\]
annotation\_groups: \[todo, deprecated\]
title: "Foo Bar"
base\_url: "http://foobar.org/api"
overwrite: false
You can optionally use the --config execution option to pass a configuration file with various pre-filled options to simplify the command we'll use to execute the tool, as seen next.
Usage
Now the configuration is done, you can access the executable from the project root in the ./vendor/bin/apigen/ directory where all packages are located. As usual, one can issue ./vendor/bin/apigen --help to get a rundown of all the execution options available.
To generate the documentation, just use ./vendor/bin/apigen generate with two simple flags, --source and --destination to specify which file, directory, or set of directories we wish to analyse. For example, this might look like the below.
./vendor/bin/apigen generate --source src/ --destination output/
And there you have it. All that remains is to navigate to the output/ location and open the contained index.html in your preferred browser to load the pages. Alternatively, one can make the generation of this documentation even easier as some IDEs and editors support it directly, for example, NetBeans.
External Interface Schema
For those of us producing APIs, whether private or public especially if it is public, a standard exists to describe the API interfaces in a consistent and program-readable JSON format called OpenAPI Specification. A popular tool for producing and presenting API schemas in this format is called Swagger.

Swagger OpenAPI specification interactive demo tool for visualising API schemas (Source: Swagger.io)
Swagger has a fantastic interactive demo for their presentation tooling which parses the autogenerated .json file (we'll come to that later) and visualises purposes, payloads, and the various responses from endpoints. Have a play with it - I'm certain the team and stakeholder benefits of which will become apparent. Pretty neat, huh?
So how do we install and use both of these parts - schema production and interactive visualisation? Visualisation depends upon your project and tooling, however, in this post I'll focus on one of the popular PHP frameworks for API construction, CakePHP. But worry not, options exist for those outside the CakePHP ecosystem.
The great thing about abstract standards and universal data formats is their parsability for most languages and open-development nature to implement its standards in any tool so check out the Swagger open-source integrations list for tools in your ecosystem to work with the OpenAPI standard and Swagger schema generation and UI! In our case, we'll use an open-source package called cakephp-swagger which integrates CakePHP with swagger-php annotation parsing. Once again, the installation was as easy as the below, which took care of all its dependencies, also.
composer require alt3/cakephp-swagger
Before we can browse our API schema documentation, we have to do three things:
- Configure and bootstrap the package with our project
- Annotate the source code
- Generate the OpenAPI JSON schema
Configuration and Bootstrapping
This depends on the version of CakePHP used in your project. If it's lower than 3.6, we tell CakePHP to load the cakephp-swagger plugin in one of two ways, via the command line (bin/cake plugin load Alt3/Swagger --routes --bootstrap) or from within config/bootstrap.php.
Plugin::load('Alt3/Swagger', ['routes' => true, 'bootstrap' => true]);
If you're in the same boat as me and use a version greater or equal to 3.6, you add the following snippet into the src/Application.php file. From here on, all steps and usages are the same regardless of the CakePHP version.
public function bootstrap() {
parent::bootstrap();
$this->addPlugin('Alt3/Swagger');
}
Now, we need to provide some details to the plugin about where we'll access the application, what protocol schemes it's accessible through (important if we want this documentation to be public), and the important locations to scan over for the annotations which will form the JSON schema.
A simpler example is available in the cakephp-swagger README, but below is an example of how to define multiple "libraries", which one can think of as a documentation namespace which produces dedicated Swagger documents - great if you use custom plugins or application namespaces. Head over to the configuration section of the README for more in-depth descriptions of the available options.

Using the above configuration, my instance of the Swagger plugin was available at http://your-app-ip-or-fqdn/swagger/docs. This route would detail the available links and documents available, as defined above.
Annotations
The key to generating an OpenAPI JSON schema is the annotations. Similar to docblocks, these describe, constrain, and group the interfaces and responses of our API. cakephp-swagger has its own flavour with syntactic variations from the OpenAPI standard it extends upon, but for the most part, the available keys and structure are rather similar and backwards-compatible as cakephp-swagger implements the same OpenAPI 2.0 standard as swagger-php. You can interrogate this difference in the swagger-php GitHub repository.
Back to the annotations. The example below represents basic health endpoint documentation. Here, we start by describing metadata which includes the application name, description, and a version of our schema documentation. In my case, I defined this in my API entry point under src/Application.php.

To describe the endpoint itself, we detail each request type, the various responses, and a definition which is essentially a way to group related endpoints.

Generation
To generate the JSON schema which the cakephp-swagger UI will read from when presenting the schema in JSON or via the included Swagger UI, one should run the below command on the host where the application is located, whether it be local or remote. For example, as in my case, the project ran within a Vagrant-managed local VM, making the host parameter the local IP the VM served upon.
bin/cake swagger makedocs [IP or fqdn]
Ta-da!
Everything is set. Simply browse to http://your-app-ip-or-fqdn/ with whatever suffix you defined in config/swagger.php.

Why does it matter?
This type of documentation is fantastically useful, descriptive, and interactive for those HTTP-based APIs which are publically available. Information like this is essential for those wishing to plug into your API - to explore and understand the locations, purposes, parameters, payloads, and various responses available.
Though, it's just as useful for internal documentation for the teams building or using APIs (whether public or private), there is a production overhead as the annotations, though structured, can clutter source files. Whilst such blocks can be collapsed in most modern editors and IDEs, the time taken to produce these annotation blocks may not be a worthwhile time investment according to the size, scale, and availability of your source code, team, or application. Of course, this may depend upon whether you're documenting as-you-go from the project's conception, or whether you're back-annotating an existing API.
What I found to be problematic with the cakephp-swagger package was the need to run within the application, itself. Though one can generate the swagger-php JSON schema independently for parsing in other ways, the inability to access the cakephp-swagger independently of the CakePHP application could complicate production environments for some teams or projects. It's something to think about how accessible this documentation might be if the API is to be private or developer-accessible only.
However, what is always useful, easy, and takes less effort and time is documenting classes and functions with parsable docblocks to have a browsable form of source documentation to understand purposes, parameters, exceptions, and return types and values. But again, this might not be as practical for vast legacy projects as newer projects due to the time requirement. Though, in my experience, spending time to document legacy projects in this way makes life significantly easier in the future to avoid and squelch duplications, misleading code re-use, syntactic errors, and more.
About the author
- Always learning; often coding. Powered by caffeine.
Comments
Join the discussionNo comments yet. Be the first to comment.




