VGTech is a blog where the developers and devops of Norways most visited website share code and tricks of the trade… Read more



Are you brilliant? We're hiring. Read more

Swagger docs in ZF2 with examples – Part 1: Setup and annotations

PHP

So everyone is building APIs now – parsing and outputting JSON is not that hard. Some people even build truly RESTful APIs, or something not to far from that.

Before, when building APIs was about SOAP with XML schemas and WSDL specifications, people spent so much time building their APIs that they had the time to think. Now, building an API is so easy and fast that the documentation is often suffering. Either because not much documentation is written in the first place, or because the API is evolving and nobody takes the time to update the documentation.

Swagger is a popular project providing auto generated API docs based on a service specification. This spec is based on annotation comments in the controllers and models, giving the developer a fairly easy, and close to the code way of keeping the API docs up to date.

In this two-part article on Swagger I will try to cover what you need to get your API docs up and running with Swagger + Swagger UI in ZF2.

Installation of skeleton app
We’ll start by cloning down a Zend Framework 2 skeleton app from github to have somewhere to start from.

Note: ZF2 is not a prerequisite for using Swagger, but in this blog post ZF2 is the context. What’s written on the topic of annotation comments and Swagger(-PHP) should apply regardless of ZF2.

Show code
git clone git://github.com/zendframework/ZendSkeletonApplication.git

Adding the swagger-php ZF2 module
The Swagger documentation view requires the API to be represented as a JSON file in the Swagger spec. format. The swagger-php ZF2 module reads the annotations in you files and generates these files.

Add the module as a requirement in the composer.json file by adding the following line:

Show code
"outeredge/swagger-module": "dev-master"

The second last thing left for the fun to begin is to add SwaggerModule to the modules array in application.config.php. The modules array in your config should look like this:

Show code
'modules' => array(
    'Application',
    'SwaggerModule'
)

When you’ve done this there’s nothing left but to install the dependencies by running composer install.

Show code
php composer.phar install

You should now have the ZF2 skeleton app set up, and if you go to the public folder under the skeleton app in your browser, you should see “Welcome to Zend Framework 2”.

Setting up the Swagger-PHP module
For the Swagger-PHP module to work we need to copy the module.swagger.global.php.dist to the config/autoloads folder of the ZF2 app and set the paths. Execute the following commands from the commandline, standing in the root of you ZF2 app.

Show code
$ cp vendor/outeredge/swagger-module/config/swagger.global.php.dist config/autoload/
$ cd config/autoload && mv swagger.global.php.dist swagger.global.php

The swagger config file is simply an array of paths to search for annotations, so wherever you decide to put your files make sure to add the path there to the swagger.global.php. We’ll get back to this file a little later when adding the last dependency.

Now we’re done setting up our ZF2 to generate the Swagger compatible JSON representation of our APIs. You should now see something like this if you go to [ZF2-public-folder]/api/docs;

Show code
{"apiVersion":null,"swaggerVersion":"1.2","apis":[]}

Important note: The controller digs through all your controllers to build the JSON files for the resources, however generating these on the fly is expensive and probably not the best idea. Swagger-PHP comes with a script (swagger.phar) for generating static JSON files and executing that as part of a build or deploy script would be much better.

Swagger UI
In order to get the nice presentation for your Swagger docs you will need Swagger UI (which will be covered in part two). In order to have somewhere to view your Swagger docs, clone the swagger-ui repository on github to somewhere outside the ZF2 app on you machine.

Show code
git clone git@github.com:wordnik/swagger-ui.git

If you open up the dist folder contained in the repo you just cloned and enter the URL to Swagger JSON docs controller ([ZF2-public-folder]/api/docs) in the top of the page, you will see the interactive Swagger docs for your API.

We’ll get back to setting up Swagger UI in ZF2, but for now let’s move on!

The annotations
I wouldn’t go so far as to say that the Swagger annotations are hard to understand, however they’re not exactly self explanatory either. What makes them tricky is the fact that there’s a lot of ways to structure the annotations. And of course the combination of a strict parser and error messages without much meaning when there’s a parsing error.

Swagger models
Model annotations are a great tool when documenting your API and gives you a way of representing output and input based on a fixed model. This is a less redundant way of documenting each endpoint rather than specifying all the parameters for each and every one.

In most cases you would simply take the model you’re using for representing the entities and documenting it with the property annotations like the example below, and use the name of the model when documenting the endpoints. Like this:

Show code
/**
* @SWG\Model(id="Message",required="recipientId, senderId, title, message")
*/
class Message {
    /**
    * @SWG\Property(name="id",type="integer",format="int64",description="Unique identifier for the Message",minimum="0.0",maximum="100.0")
    */
    public $id;

    /**
    * @SWG\Property(name="recipientId",type="integer",description="User ID identifying the recipient")
    */
    public $recipientId;
}

Partials
Swagger-PHP supports reusing annotations by naming partials and reusing them with the @SGW\Partial tag. When documenting with partials it’s important to be aware of the fact that the partial is like an extend and that the partial must be created from an annotation with no parent annotation.

Because of this, if you for instance want to make a partial of a @SWG\ResponseMessage you’re not able to do any of these:

Show code
// Won't work because of the annotation type mismatch.
/**
* @SWG\Operation(partial="myOperation", ...)
* ...
* @SWG\Api(..., @SWG\Partial("myOperation"))
*/

// Wont work because of the annotation being a 
// child of another annotation.
/**
* @SWG\Api(..., @SWG\Operation(partial="myOperation", ...)
* …
* @SWG\Operation(@SWG\Partial("myOperation"))
*/

As noted in the comment the first is caused by the annotation type type mismatch. You cannot extend an Api annotation with an Operation annotation. The other is caused by the annotation being a child of another annotation. So instead you would have to wrap the @SWG\Partial in a @SWG\ResponseMessage annotation like this;

Show code
/**
* @SWG\Operation(partial="myOperation", ...)
* ...
* @SWG\Api(..., @SWG\Operation(@SWG\Partial("myOperation")))
*/

This parent/child annotation limitation makes the partial support less useful, but I guess there’s still some cases where you could use it. For most cases though, the solution will not be partials and reusable annotations. :(

A working example in the end
For the sake of providing some actual code with annotation (which is really lacking in the Swagger-PHP documentation itself) I’ve documented a dummy controller and model with annotations.

Add the following line to composer.json in your project and add SwaggerExample to the list of modules in application.config.php, before running composer update.

Show code
"kbrabrand/zf2-swagger-example-module": "dev-master"

If you now load the Swagger UI interface and point it to the api/docs folder you should see a nicely formatted API documentation for the dummy Message controller.

I’ll follow up soon with a post on Swagger UI in ZF2, but for now; happy documenting!

PHP. Javascript. Squash. @kbrabrand


1 comments

Leave your comment