我已经实现了以下代码,以便在任何控制器的任何操作之前运行代码。但是,beforeFilter()
函数不会重定向到我指定的路由。相反,它将用户带到用户单击的位置。
//My Listener
namespace Edu'AccountBundle'EventListener;
use Symfony'Component'DependencyInjection'Container;
use Symfony'Component'HttpKernel'Event'FilterControllerEvent;
class BeforeControllerListener
{
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller))
{
//not a controller do nothing
return;
}
$controllerObject = $controller[0];
if (is_object($controllerObject) && method_exists($controllerObject, "beforeFilter"))
//Set a predefined function to execute Before any controller Executes its any method
{
$controllerObject->beforeFilter();
}
}
}
//I have registered it already
//My Controller
class LedgerController extends Controller
{
public function beforeFilter()
{
$commonFunction = new CommonFunctions();
$dm = $this->getDocumentManager();
if ($commonFunction->checkFinancialYear($dm) == 0 ) {
$this->get('session')->getFlashBag()->add('error', 'Sorry');
return $this->redirect($this->generateUrl('financialyear'));//Here it is not redirecting
}
}
}
public function indexAction() {}
请帮忙,里面缺少什么。感谢提前
我建议你遵循Symfony的建议来设置过滤器之前和之后,在过滤器本身中执行你的功能,而不是试图在执行的控制器中创建beforeFilter()
函数。 它将允许您实现您想要的 - 在每个控制器操作之前调用的函数 - 以及不必用额外的代码混淆您的控制器。 在您的情况下,您还需要将 Symfony 会话注入到过滤器中:
# app/config/services.yml
services:
app.before_controller_listener:
class: AppBundle'EventListener'BeforeControllerListener
arguments: ['@session', '@router', '@doctrine_mongodb.odm.document_manager']
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
然后,您将创建您的 before 侦听器,它将需要 Symony 会话和路由服务,以及 MongoDB 文档管理器(根据您的配置文件做出假设(。
// src/AppBundle/EventListener/BeforeControllerListener.php
namespace AppBundle'EventListener;
use Doctrine'ODM'MongoDB'DocumentManager;
use Symfony'Bundle'FrameworkBundle'Routing'Router;
use Symfony'Component'HttpFoundation'RedirectResponse;
use Symfony'Component'HttpFoundation'Session'Session;
use Symfony'Component'HttpKernel'Event'FilterControllerEvent;
use AppBundle'Controller'LedgerController;
use AppBundle'Path'To'Your'CommonFunctions;
class BeforeControllerListener
{
private $session;
private $router;
private $documentManager;
private $commonFunctions;
public function __construct(Session $session, Router $router, DocumentManager $dm)
{
$this->session = $session;
$this->router = $router;
$this->dm = $dm;
$this->commonFunctions = new CommonFunctions();
}
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
if ($controller[0] instanceof LedgerController) {
if ($this->commonFunctions->checkFinancialYear($this->dm) !== 0 ) {
return;
}
$this->session->getFlashBag()->add('error', 'Sorry');
$redirectUrl= $this->router->generate('financialyear');
$event->setController(function() use ($redirectUrl) {
return new RedirectResponse($redirectUrl);
});
}
}
}
如果您实际上使用的是Symfony CMF,那么路由器实际上可能ChainRouter
,并且路由器的use
语句将更改为use Symfony'Cmf'Component'Routing'ChainRouter;
这里还有一些其他的事情,你可能想要重新考虑 - 例如,如果CommonFunctions
类需要DocumentManager
,你可能只想使CommonFunctions
类成为自动注入DocumentManager
的服务。 然后,在此服务中,您只需注入通用函数服务而不是文档管理器。
无论哪种方式,这里发生的事情都是我们正在检查我们是否在 LedgerController
,然后检查我们是否要重定向,如果是这样,我们通过回调覆盖整个控制器。 这会设置对路由的重定向响应并执行重定向。
如果您希望对每个控制器进行此检查,则可以简单地消除对LedgerController
的检查。.
$this->redirect()
控制器函数只是创建一个RedirectResponse
的实例。与任何其他响应一样,它需要从控制器返回,或设置在事件上。您的方法不是控制器,因此您必须对事件设置响应。
但是,您不能真正在FilterControllerEvent
上设置响应,因为它旨在更新控制器或完全更改它(setController
(。您可以使用其他事件来执行此操作,例如 kernel.request
.但是,您将无法访问那里的控制器。
您可以尝试使用 setController
设置回调,这将调用您的beforeFilter()
。但是,您将无法访问控制器参数,因此如果之前 Filter 没有返回响应,您将无法真正调用原始控制器。
最后,您可以尝试抛出异常并使用异常侦听器处理它。
我不明白如果您可以在控制器中简单地调用您的方法,为什么会使事情变得如此复杂:
public function myAction()
{
if ($response = $this->beforeFilter()) {
return $response;
}
// ....
}
public function onKernelController(FilterControllerEvent $event)
{
$request = $event->getRequest();
$response = new Response();
// Matched route
$_route = $request->attributes->get('_route');
// Matched controller
$_controller = $request->attributes->get('_controller');
$params = array(); //Your params
$route = $event->getRequest()->get('_route');
$redirectUrl = $url = $this->container->get('router')->generate($route,$params);
$event->setController(function() use ($redirectUrl) {
return new RedirectResponse($redirectUrl);
});
}
干杯!!