我可以执行重定向到服务中的另一个控制器吗?
我已根据@Artamiel提供的示例实施了一项服务。
我的控制器执行的功能代码如下所示:
public function verifyanddispatch() {
$session = $this->request->getSession();
if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->router->generate('app_listbooks'));
}
我已经检查过!$session->get("App_Books_Chosen_Lp")
是真的。尽管如此,我并没有被重定向到app_listbooks
控制器。
我认为这是因为我不直接在控制器中而不是在服务中返回重定向响应。
答案 0 :(得分:12)
我不知道您是如何定义服务的,但下面的示例工作正常。假设您正在从控制器呼叫服务。
<强> services.yml 强>
services:
application_backend.service.user:
class: Application\BackendBundle\Service\UserService
arguments:
- @router
服务类
namespace Application\BackendBundle\Service;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
class UserService
{
private $router;
public function __construct(
RouterInterface $router
) {
$this->router = $router;
}
public function create()
{
$user = new User();
$user->setUsername('hello');
$this->entityManager->persist($user);
$this->entityManager->flush();
return new RedirectResponse($this->router->generate('application_frontend_default_index'));
}
}
<强>控制器强>
public function createAction(Request $request)
{
//.........
return $this->userService->create();
}
<强>更新强>
虽然上面的原始答案回答了原始问题,但这不是最佳实践,如果您想要更好的方法,请执行以下操作。首先,不要将@router
注入服务并执行以下更改。
// Service
public function create()
{
.....
$user = new User();
$user->setUsername('hello');
$this->entityManager->persist($user);
$this->entityManager->flush();
.....
}
// Controller
public function createAction(Request $request)
{
try {
$this->userService->create();
return new RedirectResponse($this->router->generate(........);
} catch (......) {
throw new BadRequestHttpException(.....);
}
}
答案 1 :(得分:5)
从架构的角度来看,不应该在服务中创建redirectResponse。一种方法是,在服务中抛出异常,这可以在控制器操作中捕获,您可以轻松创建RedirectResponse。
可在此处找到一个示例:Redirect from a Service in Symfony2
答案 2 :(得分:1)
我同意@Moritz的说法,重定向必须在控制器内完成。
但有时候如果从控制器内的本地函数完成某些重定向会很有用。
在这种情况下,解决方案可能是创建自定义异常类(RedirectException)。
在这里,您可以找到有趣帖子的链接:https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-faq。
我知道这是有争议的,但如果它在其控制器内的本地功能中使用,则有意义。
总结一下,步骤如下:
1)创建一个RedirectException类
2)创建内核侦听器
3)在配置服务文件(service.yml)中设置服务
4)在必要时使用url抛出异常以重定向。
答案 3 :(得分:0)
似乎从服务重定向你必须向控制器传递RedirectResponse
对象或值,它将告诉控制器服务中的所有内容都很好并且不需要重定向(例如下面的例子:“true”值)。然后你必须在控制器中验证提供了哪个值(无论是“真”还是RedirectResponse
)并在控制器内再次返回RedirectResponse
或者什么都不做。
下面的示例应该说明一切。
服务:
<?php
namespace AppBundle\Service;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
class nobookchoosenService {
/* @var $request Request */
private $request;
/* @var $router RouterInterface */
private $router;
public function __construct(RequestStack $requestStack, RouterInterface $router) {
$this->request = $requestStack->getCurrentRequest();
$this->router = $router;
}
public function verifyanddispatch() {
$session = $this->request->getSession();
if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->router->generate('app_listbooks'));
else return true;
}
}
控制器:
$checker = $this->get('nobookchoosen_service')->verifyanddispatch();
if($checker != "true") return $checker;
答案 4 :(得分:0)
这是可能的,但我不推荐它。要从服务重定向,您应该为您的事件提供正确的API
,例如:FOSUserBundle
您正在接收FilterUserResponseEvent
的实例,并且您可以设置对该事件对象的响应:
class RegistrationListener implements EventSubscriberInterface
{
// dependencies
// ...
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onSuccess',
);
}
public function onSuccess(FilterUserResponseEvent $event)
{
$url = $this->router->generate('some_url');
$event->setResponse(new RedirectResponse($url));
}
}
这要归功于控制器:
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
if (null === $response = $event->getResponse()) {
// create response
}
// return response from event