我一直髮現有關自定義註釋的文檔有點欠缺。但希望以下將幫助你。
先決條件:
- 您需要標註爲
@Annotation
類。對於annotion使用的所有參數,這將作爲容器。
- 您需要一個適當的事件偵聽器來查找並讀取註釋並按照相應的方式進行操作。
註解類
對於這個工作,你需要定義所有的屬性,可以用來爲您的自定義註釋(這裏route, route_params, required
),作爲類屬性。
<?php
// src/AppBundle/Annotation/RedirectOnMissing.php
namespace AppBundle\Annotation;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @Annotation
*/
class RedirectOnMissing
{
/**
* @var string
*/
private $route;
/**
* @var array
*/
private $route_params = [];
/**
* @var array
*/
private $required = [];
/**
* @param array $options
*/
public function __construct(array $options)
{
$options = $this->configureOptions(new OptionsResolver())->resolve($options);
$this->route = $options['route'];
$this->route_params = $options['route_params'];
$this->required = $options['required'];
}
/**
* @param OptionsResolver $resolver
*
* @return OptionsResolver
*/
private function configureOptions(OptionsResolver $resolver)
{
return $resolver
->setRequired(['route', 'required'])
->setDefaults([
'route_params' => []
])
->setAllowedTypes('route', 'string')
->setAllowedTypes('required', 'array')
->setAllowedTypes('route_params', 'array')
;
}
/**
* Get `route`
*
* @return string
*/
public function getRoute()
{
return $this->route;
}
/**
* Get `route_params`
*
* @return array
*/
public function getRouteParams()
{
return $this->route_params;
}
/**
* Get `required`
*
* @return string[]
*/
public function getRequired()
{
return $this->required;
}
}
你需要聽kernel.controller
事件,否則您將無法訪問活躍控制器的聽衆。
<?php
// src/AppBundle/EventListener/FilterControllerListener.php
namespace AppBundle\EventListener;
use AppBundle\Annotation\RedirectOnMissing;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation as Http;
class FilterControllerListener
{
/**
* @var Reader
*/
private $reader;
/**
* @var UrlGeneratorInterface
*/
private $urlGenerator;
/**
* @var SessionInterface
*/
private $session;
/**
* @param Reader $reader
* @param UrlGeneratorInterface $urlGenerator
* @param SessionInterface $session
*/
public function __construct(Reader $reader, UrlGeneratorInterface $urlGenerator, SessionInterface $session)
{
$this->reader = $reader;
$this->urlGenerator = $urlGenerator;
$this->session = $session;
}
/**
* @param FilterControllerEvent $event
*/
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
/** @var $methodAnnotation RedirectOnMissing */
$methodAnnotation = $this->reader->getMethodAnnotation(
new \ReflectionMethod($controller[0], $controller[1]),
RedirectOnMissing::class
);
if (null !== $methodAnnotation) {
foreach ($methodAnnotation->getRequired() as $key) {
if (!$this->session->has($key)) {
$event->setController(function() use($methodAnnotation) {
return new Http\RedirectResponse($this->urlGenerator->generate($methodAnnotation->getRoute(), $methodAnnotation->getRouteParams()));
});
break;
}
}
}
}
}
配置
// src/AppBundle/Resources/config/services.yml
services:
// ...
app.event_listner.controller_listener:
class: AppBundle\EventListener\FilterControllerListener
arguments:
- "@annotation_reader"
- "@router"
- "@session"
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
使用
<?php
/**
* @Cfg\Route("/test")
*
* @RedirectOnMissing(route="home", required={"foo", "bar"})
*/
public function testAction()
{
return new Http\Response('no redirect');
}
注:使用定製標註處理,它可能是你需要清除緩存經常能看到的變化。
哇!你應該提交一個公關與這個答案作爲新的食譜:)謝謝你這個質量的答案。 –