I'm using Symfony framework and have intention do add auto-documentation engine to RESTful api of my project.
After some searching I've found apidoc engine (http://apidocjs.com/). It works pretty simple: you have to add some annotations for every controller of you RESTful api and documentation will generated.
The example of annotation is:
/**
* @Route("/api/dictionary_list/{userId}/{sessionKey}", name="api/dictionary_list")
* @api {get} /api/dictionary_list/{userId}/{sessionKey} 01. Values list (ids) for all system dictionaries
* @apiName Dictionary list
* @apiGroup Dictionary
*
* @apiParam {Integer} userId User's ID received in authorization request
* @apiParam {String} sessionKey Session key received in authorization request
*
* @apiSuccess {Integer} parcelStatuses The name of current dictionary
* @apiSuccess {String} itemId Item id which used in requests
* @apiSuccess {String} itemName Item name
*/
public function dictionaryListAction($userId=null, $sessionKey=null)
{
...
}
As you can see, annotation for apidoc is the same as the annotation for routing in Symfony.
By the way in production environment it works fine, but in development environment I get exception like
[Semantical Error] The annotation "@apiName" in method AppBundle\Controller\Api\apiDictionaryController::dictionaryListAction() was never imported.
Is there any way to fix this issue and say to Symfony that annotation for apidoc have to be ignored?
You can use the IgnoreAnnotation
annotation to tell Docrine annotation reader to skip this annotation in your controller. To do this, simply put the annotation add @IgnoreAnnotation("Annotation")
to the class doc comment of class.
In you case:
/**
* @IgnoreAnnotation("apiName")
* @IgnoreAnnotation("apiGroup")
* @IgnoreAnnotation("apiParam")
* @IgnoreAnnotation("apiSuccess")
*/
class ActionController extends Controller
/**
* @Route("/api/dictionary_list/{userId}/{sessionKey}", name="api/dictionary_list")
* @api {get} /api/dictionary_list/{userId}/{sessionKey} 01. Values list (ids) for all system dictionaries
* @apiName Dictionary list
* @apiGroup Dictionary
*
* @apiParam {Integer} userId User's ID received in authorization request
* @apiParam {String} sessionKey Session key received in authorization request
*
* @apiSuccess {Integer} parcelStatuses The name of current dictionary
* @apiSuccess {String} itemId Item id which used in requests
* @apiSuccess {String} itemName Item name
*/
public function dictionaryListAction($userId=null, $sessionKey=null)
{
...
}
You could also consider to open a PR to the doctrine/annotations project to include this annotation as default skipped as this one.
Hope this help.
Symfony uses the doctrine/annotations package to parse annotations. When it encounters an unkown annotation that hasn't been blacklisted it throws an exception.
You can blacklist additional annotations, see Doctrine docs - Ignoring missing exceptions:
use Doctrine\Common\Annotations\AnnotationReader;
AnnotationReader::addGlobalIgnoredName('api');
AnnotationReader::addGlobalIgnoredName('apiParam');
AnnotationReader::addGlobalIgnoredName('apiGroup');
AnnotationReader::addGlobalIgnoredName('apiSuccess');
I'd put this in app/autoload.php since it's a global setting.
Annotations are read during DI Container compilation so it may be a better idea to ignore the apidocs annotations during compiler pass.
Example:
<?php
namespace YourBundle\DependencyInjection;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class IgnoreApiDocsAnnotationsPass implements CompilerPassInterface {
public function process(ContainerBuilder $container) {
AnnotationReader::addGlobalIgnoredName('api');
AnnotationReader::addGlobalIgnoredName('apiDefine');
AnnotationReader::addGlobalIgnoredName('apiDeprecated');
AnnotationReader::addGlobalIgnoredName('apiDescription');
AnnotationReader::addGlobalIgnoredName('apiError');
AnnotationReader::addGlobalIgnoredName('apiErrorExample');
AnnotationReader::addGlobalIgnoredName('apiExample');
AnnotationReader::addGlobalIgnoredName('apiGroup');
AnnotationReader::addGlobalIgnoredName('apiHeader');
AnnotationReader::addGlobalIgnoredName('apiHeaderExample');
AnnotationReader::addGlobalIgnoredName('apiIgnore');
AnnotationReader::addGlobalIgnoredName('apiName');
AnnotationReader::addGlobalIgnoredName('apiParam');
AnnotationReader::addGlobalIgnoredName('apiParamExample');
AnnotationReader::addGlobalIgnoredName('apiPermission');
AnnotationReader::addGlobalIgnoredName('apiPrivate');
AnnotationReader::addGlobalIgnoredName('apiSampleRequest');
AnnotationReader::addGlobalIgnoredName('apiSuccess');
AnnotationReader::addGlobalIgnoredName('apiSuccessExample');
AnnotationReader::addGlobalIgnoredName('apiUse');
AnnotationReader::addGlobalIgnoredName('apiVersion');
}
}
I obtainted the full list of annotation from the apidoc docs. You need to register the compiler pass in your bundle with
<?php
namespace YourBundle;
use YourBundle\DependencyInjection\IgnoreApiDocsAnnotationsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class YourBundle extends Bundle {
public function build(ContainerBuilder $container) {
parent::build($container);
$container->addCompilerPass(new IgnoreApiDocsAnnotationsPass());
}
}
You have to import Route :
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;