Reputation: 1305
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?
Upvotes: 5
Views: 6670
Reputation: 21249
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());
}
}
Upvotes: 1
Reputation: 49
You have to import Route :
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
Upvotes: -1
Reputation: 39380
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.
Upvotes: 2
Reputation: 6560
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.
Upvotes: 1