2013-11-14 11:43:09 +01:00
NelmioApiDocBundle
==================
The **NelmioApiDocBundle** bundle allows you to generate a decent documentation
for your APIs.
2013-12-05 17:10:38 +01:00
Installation
------------
2013-11-14 11:43:09 +01:00
2014-10-21 21:24:58 +01:00
Require the `nelmio/api-doc-bundle` package in your composer.json and update your dependencies.
2013-11-14 11:43:09 +01:00
2014-10-21 21:24:58 +01:00
$ composer require nelmio/api-doc-bundle
2013-12-05 17:10:38 +01:00
2013-11-14 11:43:09 +01:00
Register the bundle in `app/AppKernel.php` :
2015-04-28 23:29:18 +02:00
```php
2014-09-21 05:04:16 +04:00
// app/AppKernel.php
public function registerBundles()
{
return array(
// ...
new Nelmio\ApiDocBundle\NelmioApiDocBundle(),
);
}
```
2013-11-14 11:43:09 +01:00
Import the routing definition in `routing.yml` :
2014-07-31 10:18:25 -07:00
```yaml
# app/config/routing.yml
NelmioApiDocBundle:
resource: "@NelmioApiDocBundle/Resources/config/routing .yml"
prefix: /api/doc
```
2013-11-14 11:43:09 +01:00
Enable the bundle's configuration in `app/config/config.yml` :
2015-04-28 23:29:18 +02:00
```yaml
2014-07-31 10:18:25 -07:00
# app/config/config.yml
nelmio_api_doc: ~
```
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
Usage
-----
2013-11-14 11:43:09 +01:00
The main problem with documentation is to keep it up to date. That's why the **NelmioApiDocBundle**
uses introspection a lot. Thanks to an annotation, it's really easy to document an API method.
2013-12-05 17:10:38 +01:00
### The ApiDoc() Annotation
2013-11-14 11:43:09 +01:00
The bundle provides an `ApiDoc()` annotation for your controllers:
2015-04-28 23:29:18 +02:00
```php
2013-11-14 11:43:09 +01:00
< ?php
namespace Your\Namespace;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
class YourController extends Controller
{
/**
2014-03-28 10:46:38 +00:00
* This is the documentation description of your method, it will appear
2013-11-14 11:43:09 +01:00
* on a specific pane. It will read all the text until the first
* annotation.
*
* @ApiDoc (
* resource=true,
* description="This is a description of your API method",
* filters={
* {"name"="a-filter", "dataType"="integer"},
* {"name"="another-filter", "dataType"="string", "pattern"="(foo|bar) ASC|DESC"}
* }
* )
*/
public function getAction()
{
}
/**
* @ApiDoc (
* description="Create a new Object",
* input="Your\Namespace\Form\Type\YourType",
* output="Your\Namespace\Class"
* )
*/
public function postAction()
{
}
/**
* @ApiDoc (
* description="Returns a collection of Object",
* requirements={
* {
* "name"="limit",
* "dataType"="integer",
* "requirement"="\d+",
* "description"="how many objects to return"
* }
* },
* parameters={
* {"name"="categoryId", "dataType"="integer", "required"=true, "description"="category id"}
* }
* )
*/
public function cgetAction($id)
{
}
}
```
The following properties are available:
* `section` : allow to group resources
* `resource` : whether the method describes a main resource or not (default: `false` );
* `description` : a description of the API method;
2014-02-06 09:27:30 -08:00
* `https` : whether the method described requires the https protocol (default: `false` );
2013-11-14 11:43:09 +01:00
* `deprecated` : allow to set method as deprecated (default: `false` );
2014-07-19 13:43:39 +02:00
* `tags` : allow to tag a method (e.g. `beta` or `in-development` ). Either a single tag or an array of tags. Each tag can have an optional hex colorcode attached.
2015-04-28 23:29:18 +02:00
```php
2014-07-19 13:43:39 +02:00
< ?php
class YourController
{
/**
* @ApiDoc (
* tags={
* "stable",
* "deprecated" = "#ff0000 "
* }
* )
*/
public function myFunction()
{
// ...
}
}
```
2014-05-27 19:33:52 +02:00
2013-11-14 11:43:09 +01:00
* `filters` : an array of filters;
* `requirements` : an array of requirements;
* `parameters` : an array of parameters;
* `input` : the input type associated to the method (currently this supports Form Types, classes with JMS Serializer
metadata, and classes with Validation component metadata) useful for POST|PUT methods, either as FQCN or as form type
(if it is registered in the form factory in the container).
* `output` : the output type associated with the response. Specified and parsed the same way as `input` .
* `statusCodes` : an array of HTTP status codes and a description of when that status is returned; Example:
2015-04-28 23:29:18 +02:00
```php
2013-11-14 11:43:09 +01:00
< ?php
class YourController
{
/**
* @ApiDoc (
* statusCodes={
* 200="Returned when successful",
* 403="Returned when the user is not authorized to say hello",
* 404={
* "Returned when the user is not found",
2014-01-21 10:41:55 +01:00
* "Returned when something else is not found"
2013-11-14 11:43:09 +01:00
* }
* }
* )
*/
public function myFunction()
{
// ...
}
}
```
Each _filter_ has to define a `name` parameter, but other parameters are free. Filters are often optional
parameters, and you can document them as you want, but keep in mind to be consistent for the whole documentation.
If you set `input` , then the bundle automatically extracts parameters based on the given type,
and determines for each parameter its data type, and if it's required or not.
For classes parsed with JMS metadata, description will be taken from the properties doc comment, if available.
For Form Types, you can add an extra option named `description` on each field:
2015-04-28 23:29:18 +02:00
```php
2013-11-14 11:43:09 +01:00
< ?php
class YourType extends AbstractType
{
/**
* {@inheritdoc }
*/
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('note', null, array(
'description' => 'this is a note',
));
// ...
}
}
```
The bundle will also get information from the routing definition (`requirements` , `pattern` , etc), so to get the
best out of it you should define strict _method requirements etc.
2013-12-05 17:10:38 +01:00
### Other Bundle Annotations
2013-11-14 11:43:09 +01:00
Also bundle will get information from the other annotations:
* @FOS \RestBundle\Controller\Annotations\RequestParam - use as `parameters`
* @FOS \RestBundle\Controller\Annotations\QueryParam - use as `requirements` (when strict parameter is true), `filters` (when strict is false)
2014-01-13 14:53:28 +03:00
* @JMS \SecurityExtraBundle\Annotation\Secure - set `authentication` to true, `authenticationRoles` to the given roles
2013-11-14 11:43:09 +01:00
* @Sensio \Bundle\FrameworkExtraBundle\Configuration\Cache - set `cache`
2013-12-05 17:10:38 +01:00
### PHPDoc
2013-11-14 11:43:09 +01:00
2014-12-11 12:11:51 +01:00
Actions marked as @deprecated will be marked as such in the interface.
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
#### JMS Serializer Features
2013-11-14 11:43:09 +01:00
2014-12-11 12:11:51 +01:00
The bundle has support for some of the JMS Serializer features and uses this
extra piece of information in the generated documentation.
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
##### Group Exclusion Strategy
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
If your classes use [JMS Group Exclusion
Strategy](http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies#creating -different-views-of-your-objects),
you can specify which groups to use when generating the documentation by using
this syntax :
2013-11-14 11:43:09 +01:00
```
input={
"class"="Acme\Bundle\Entity\User",
"groups"={"update", "public"}
}
```
2013-12-05 17:10:38 +01:00
In this case the groups 'update' and 'public' are used.
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
This feature also works for the `output` property.
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
##### Versioning Objects
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
If your `output` classes use [versioning capabilities of JMS
Serializer](http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies#versioning -objects),
the versioning information will be automatically used when generating the
documentation.
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
#### Form Types Features
2013-11-14 11:43:09 +01:00
2014-07-01 12:29:58 +03:00
Even if you use `FormFactoryInterface::createNamed('', 'your_form_type')` the documentation will generate the form type name as the prefix for inputs
2013-12-05 17:10:38 +01:00
(`your_form_type[param]` ... instead of just `param` ).
2013-11-14 11:43:09 +01:00
2014-07-01 12:29:58 +03:00
You can specify which prefix to use with the `name` key in the `input` section:
2013-11-14 11:43:09 +01:00
```
input = {
"class" = "your_form_type",
"name" = ""
}
```
2015-03-13 15:33:45 +01:00
You can also add some options to pass to the form. You just have to use the `options` key:
```
input = {
"class" = "your_form_type",
"options" = {"method" => "PUT"},
}
```
2014-01-10 11:16:09 +01:00
#### Used Parsers
2013-12-05 00:05:47 +01:00
By default, all registered parsers are used, but sometimes you may want to
define which parsers you want to use. The `parsers` attribute is used to
configure a list of parsers that will be used:
```
output={
"class" = "Acme\Bundle\Entity\User",
"parsers" = {
"Nelmio\ApiDocBundle\Parser\JmsMetadataParser",
"Nelmio\ApiDocBundle\Parser\ValidationParser"
}
}
```
In this case the parsers `JmsMetadataParser` and `ValidationParser` are used to
generate returned data.
This feature also works for both the `input` and `output` properties.
2014-01-10 11:16:09 +01:00
### Web Interface
You can browse the whole documentation at: `http://example.org/api/doc` .
![](https://github.com/nelmio/NelmioApiDocBundle/raw/master/Resources/doc/webview.png)
![](https://github.com/nelmio/NelmioApiDocBundle/raw/master/Resources/doc/webview2.png)
2013-12-05 00:05:47 +01:00
2013-12-05 17:10:38 +01:00
### On-The-Fly Documentation
2013-11-14 11:43:09 +01:00
2013-12-05 17:10:38 +01:00
By calling an URL with the parameter `?_doc=1` , you will get the corresponding
documentation if available.
2013-11-14 11:43:09 +01:00
2014-01-10 11:16:09 +01:00
### Sandbox
2013-11-14 11:43:09 +01:00
2014-01-10 11:16:09 +01:00
This bundle provides a sandbox mode in order to test API methods. You can
configure this sandbox using the following parameters:
2014-07-31 10:18:25 -07:00
```yaml
# app/config/config.yml
nelmio_api_doc:
sandbox:
authentication: # default is `~` (`null` ), if set, the sandbox automatically
# send authenticated requests using the configured `delivery`
2013-11-14 11:43:09 +01:00
2014-07-31 10:18:25 -07:00
name: access_token # access token name or query parameter name or header name
2014-07-25 12:08:00 +02:00
2014-07-31 10:18:25 -07:00
delivery: http # `query` , `http` , and `header` are supported
2013-11-14 11:43:09 +01:00
2014-07-31 10:18:25 -07:00
# Required if http delivery is selected.
type: basic # `basic` , `bearer` are supported
2014-01-10 11:16:09 +01:00
2014-07-31 10:18:25 -07:00
custom_endpoint: true # default is `false` , if `true` , your user will be able to
# specify its own endpoint
2014-01-10 11:16:09 +01:00
2014-07-31 10:18:25 -07:00
enabled: true # default is `true` , you can set this parameter to `false`
# to disable the sandbox
2014-01-10 11:16:09 +01:00
2014-07-31 10:18:25 -07:00
endpoint: http://sandbox.example.com/ # default is `/app_dev.php` , use this parameter
# to define which URL to call through the sandbox
2014-01-10 11:16:09 +01:00
2014-07-31 10:18:25 -07:00
accept_type: application/json # default is `~` (`null` ), if set, the value is
# automatically populated as the `Accept` header
2014-01-10 11:29:10 +01:00
2014-07-31 10:18:25 -07:00
body_format:
formats: [ form, json ] # array of enabled body formats,
# remove all elements to disable the selectbox
default_format: form # default is `form` , determines whether to send
# `x-www-form-urlencoded` data or json-encoded
# data (by setting this parameter to `json` ) in
# sandbox requests
2014-05-17 22:45:30 +02:00
2014-07-31 10:18:25 -07:00
request_format:
formats: # default is `json` and `xml` ,
json: application/json # override to add custom formats or disable
xml: application/xml # the default formats
2014-01-10 11:16:09 +01:00
2014-07-31 10:18:25 -07:00
method: format_param # default is `format_param` , alternately `accept_header` ,
# decides how to request the response format
2013-11-14 11:43:09 +01:00
2014-07-31 10:18:25 -07:00
default_format: json # default is `json` ,
# default content format to request (see formats)
```
2013-12-05 17:10:38 +01:00
### Command
2013-11-14 11:43:09 +01:00
A command is provided in order to dump the documentation in `json` , `markdown` , or `html` .
php app/console api:doc:dump [--format="..."]
The `--format` option allows to choose the format (default is: `markdown` ).
For example to generate a static version of your documentation you can use:
php app/console api:doc:dump --format=html > api.html
By default, the generated HTML will add the sandbox feature if you didn't disable it in the configuration.
If you want to generate a static version of your documentation without sandbox, use the `--no-sandbox` option.
2014-07-31 10:18:25 -07:00
### Swagger support
2014-01-10 11:16:09 +01:00
2014-12-11 12:11:51 +01:00
Read the [documentation for Swagger integration ](https://github.com/nelmio/NelmioApiDocBundle/blob/master/Resources/doc/swagger-support.md )
for the necessary steps to make a Swagger-compliant documentation for your API.
2013-11-14 11:43:09 +01:00
2015-04-28 23:29:18 +02:00
### DunglasApiBundle support
This bundle recognizes and documents resources exposed with [DunglasApiBundle ](https://github.com/dunglas/DunglasApiBundle ).
Just install NelmioApiDoc and the documentation will be automatically available. To enable the sandbox, use the following
configuration:
```yaml
# app/config/config.yml
nelmio_api_doc:
sandbox:
accept_type: "application/json"
body_format:
formats: [ "json" ]
default_format: "json"
request_format:
formats:
json: "application/json"
```
2014-07-31 10:18:25 -07:00
### Caching
2013-11-14 11:43:09 +01:00
2014-07-31 10:18:25 -07:00
It is a good idea to enable the internal caching mechanism on production:
2015-04-28 23:29:18 +02:00
```yaml
# app/config/config.yml
nelmio_api_doc:
cache:
enabled: true
```
2014-07-25 12:08:00 +02:00
2014-07-31 10:18:25 -07:00
Configuration In-Depth
----------------------
2014-07-25 12:08:00 +02:00
2014-07-31 10:18:25 -07:00
You can specify your own API name:
```
# app/config/config.yml
nelmio_api_doc:
name: My API
```
You can choose between different authentication methods:
```yaml
# app/config/config.yml
nelmio_api_doc:
2015-02-06 15:54:35 +01:00
sandbox:
authentication:
delivery: header
name: X-Custom
2014-07-25 12:08:00 +02:00
2014-07-31 10:18:25 -07:00
# app/config/config.yml
nelmio_api_doc:
2015-02-06 15:54:35 +01:00
sandbox:
authentication:
delivery: query
name: param
2014-07-31 10:18:25 -07:00
# app/config/config.yml
nelmio_api_doc:
2015-02-06 15:54:35 +01:00
sandbox:
authentication:
delivery: http
type: basic # or bearer
2014-07-31 10:18:25 -07:00
```
2014-07-25 12:08:00 +02:00
When choosing an `http` delivery, `name` defaults to `Authorization` ,
and the header value will automatically be prefixed by the corresponding type (ie. `Basic` or `Bearer` ).
2014-01-16 13:42:37 +01:00
You can specify which sections to exclude from the documentation generation:
2014-07-31 10:18:25 -07:00
```yaml
# app/config/config.yml
nelmio_api_doc:
exclude_sections: ["privateapi", "testapi"]
```
2014-01-10 11:16:09 +01:00
The bundle provides a way to register multiple `input` parsers. The first parser
that can handle the specified input is used, so you can configure their
priorities via container tags. Here's an example parser service registration:
2014-07-31 10:18:25 -07:00
```yaml
# app/config/config.yml
services:
mybundle.api_doc.extractor.custom_parser:
class: MyBundle\Parser\CustomDocParser
tags:
- { name: nelmio_api_doc.extractor.parser, priority: 2 }
```
2014-01-10 11:16:09 +01:00
You can also define your own motd content (above methods list). All you have to
do is add to configuration:
2014-07-31 10:18:25 -07:00
```yaml
# app/config/config.yml
nelmio_api_doc:
# ...
motd:
template: AcmeApiBundle::Components/motd.html.twig
2014-12-11 12:11:51 +01:00
```
2014-07-31 10:18:25 -07:00
You can define an alternate location where the ApiDoc configurations are to be cached:
```yaml
# app/config/config.yml
nelmio_api_doc:
cache:
enabled: true
file: "/tmp/symfony-app/%kernel.environment%/api-doc.cache"
```
2013-12-05 17:10:38 +01:00
### Using Your Own Annotations
2013-11-14 11:43:09 +01:00
If you have developed your own project-related annotations, and you want to parse them to populate
the `ApiDoc` , you can provide custom handlers as services. You just have to implement the
`Nelmio\ApiDocBundle\Extractor\HandlerInterface` and tag it as `nelmio_api_doc.extractor.handler` :
2014-07-31 10:18:25 -07:00
```yaml
# app/config/config.yml
services:
mybundle.api_doc.extractor.my_annotation_handler:
class: MyBundle\AnnotationHandler\MyAnnotationHandler
tags:
- { name: nelmio_api_doc.extractor.handler }
```
2013-11-14 11:43:09 +01:00
Look at the built-in [Handlers ](https://github.com/nelmio/NelmioApiDocBundle/tree/master/Extractor/Handler ).
2013-12-05 17:10:38 +01:00
2014-12-11 12:11:51 +01:00
### Configuration Reference
2013-12-05 17:10:38 +01:00
``` yaml
nelmio_api_doc:
2014-06-27 14:13:36 +02:00
name: 'API documentation'
exclude_sections: []
2014-08-23 16:57:40 +02:00
default_sections_opened: true
2013-12-05 17:10:38 +01:00
motd:
2014-06-27 14:13:36 +02:00
template: 'NelmioApiDocBundle::Components/motd.html.twig'
2013-12-05 17:10:38 +01:00
request_listener:
enabled: true
parameter: _doc
sandbox:
enabled: true
2014-06-27 14:13:36 +02:00
endpoint: null
accept_type: null
body_format:
formats:
# Defaults:
- form
- json
default_format: ~ # One of "form"; "json"
2013-12-05 17:10:38 +01:00
request_format:
2014-05-17 22:45:30 +02:00
formats:
2014-06-27 14:13:36 +02:00
# Defaults:
json: application/json
xml: application/xml
method: ~ # One of "format_param"; "accept_header"
2013-12-05 17:10:38 +01:00
default_format: json
authentication:
delivery: ~ # Required
2014-07-30 11:10:39 +02:00
name: ~ # Required
# Required if http delivery is selected.
type: ~ # One of "basic"; "bearer"
2013-12-05 17:10:38 +01:00
custom_endpoint: false
2014-07-31 10:18:25 -07:00
swagger:
api_base_path: /api
swagger_version: '1.2'
api_version: '0.1'
info:
title: Symfony2
description: 'My awesome Symfony2 app!'
TermsOfServiceUrl: null
contact: null
license: null
licenseUrl: null
cache:
enabled: false
file: '%kernel.cache_dir%/api-doc.cache'
2013-12-05 17:10:38 +01:00
```