我已经实现了以下代码,可以在任何控制器的任何操作之前运行代码。但是,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() {}
请帮忙,里面缺少什么。 谢谢你的进步
答案 0 :(得分:2)
$this->redirect()
控制器函数只创建RedirectResponse
的实例。与任何其他响应一样,它需要从控制器返回,或者在事件上设置。您的方法不是控制器,因此您必须在事件上设置响应。
但是,您无法在FilterControllerEvent
上设置响应,因为它要么更新控制器,要么完全更改(setController
)。您可以使用其他活动执行此操作,例如kernel.request
。但是,您无法访问那里的控制器。
您可以尝试使用setController
设置回调,该回调会调用您的beforeFilter()
。但是,您将无法访问控制器参数,因此如果beforeFilter未返回响应,您将无法真正调用原始控制器。
最后,您可能会尝试抛出异常并使用异常侦听器处理它。
如果你只需要在控制器中调用你的方法,我就不明白为什么要把事情变得复杂:
public function myAction()
{
if ($response = $this->beforeFilter()) {
return $response;
}
// ....
}
答案 1 :(得分:2)
我建议您按照setting up before and after filters的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 }
然后,您将创建您的之前的侦听器,它将需要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
,然后检查我们是否要重定向,如果是,我们通过回调覆盖整个Controller。这会将重定向响应设置为您的路由并执行重定向。
如果您希望对每个控制器进行此检查,则可以简单地取消对LedgerController
的检查。
答案 2 :(得分:1)
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);
});
}
干杯!!