简体   繁体   English

服务中的重定向 - symfony2

[英]Redirecting in service - symfony2

May I perform redirection to another controller within service?我可以重定向到服务中的另一个控制器吗?

I have implemented a service based on example provided by @Artamiel .我已经基于@Artamiel提供的示例实现了一项服务。

My function code which is executed by controller looks like this:我的由控制器执行的功能代码如下所示:

 public function verifyanddispatch() {
        $session = $this->request->getSession();
        if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->router->generate('app_listbooks'));
    }

I have checked and !$session->get("App_Books_Chosen_Lp") is true.我已经检查过!$session->get("App_Books_Chosen_Lp")是真的。 Nonetheless I am not redirected to app_listbooks controller.尽管如此,我并没有被重定向到app_listbooks控制器。

I think that this is because I return redirect response not directly in controller rather than in a service.我认为这是因为我不直接在控制器中而不是在服务中返回重定向响应。

I don't know how you defined your service but example below works fine.我不知道你是如何定义你的服务的,但下面的例子工作正常。 Assuming that you're calling service from your controller.假设您正在从控制器调用服务。

services.yml服务.yml

services:
    application_backend.service.user:
        class: Application\BackendBundle\Service\UserService
        arguments:
            - @router

Service class服务类

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'));
    }
}

Controller控制器

public function createAction(Request $request)
{
    //.........

    return $this->userService->create();
}

UPDATE更新


Although original answer above answers original question, it is not the best practise so do the following if you want a better way.尽管上面的原始答案回答了原始问题,但这不是最佳做法,因此如果您想要更好的方法,请执行以下操作。 First of all do not inject @router into service and do the following changes.首先不要将@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(.....);    
    }
}

From an architecture point of view one should not create a RedirectResponse in a service.从架构的角度来看,不应在服务中创建RedirectResponse One way could be to throw an exception in the service, which is caught in the controller's action where you can easily create a RedirectResponse .一种方法可能是在服务中抛出异常,该异常在控制器的操作中被捕获,您可以在其中轻松创建RedirectResponse

An example can be found here: Redirect from a Service in Symfony2可以在此处找到示例: 从 Symfony2 中的服务重定向

It seems to make the redirection from service you have to pass to controller either RedirectResponse object or value that will tell controller that everything within service went fine and no redirection is needed (in example below: "true" value).它似乎使从服务的重定向您必须传递给控制器RedirectResponse对象或值,它将告诉控制器服务中的一切正常并且不需要重定向(在下面的示例中:“true”值)。 Then you have to verify in controller which value was provided (whether it is "true" or RedirectResponse ) and either return RedirectResponse again within controller or do nothing.然后您必须在控制器中验证提供了哪个值(无论是“true”还是RedirectResponse ),然后在控制器中再次返回RedirectResponse或什么都不做。

Example below should tell everything.下面的例子应该说明一切。

Service:服务:

<?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;
    }

}

Controller:控制器:

$checker = $this->get('nobookchoosen_service')->verifyanddispatch();
        if($checker != "true") return  $checker;

I am agree with @Moritz that redirections must be done inside controllers.我同意@Moritz 的观点,即重定向必须在控制器内部完成。

But sometimes happens that some redirection would be useful if done from a local function inside a controller.但有时会发生,如果从控制器内的本地函数完成某些重定向会很有用。

In this case a solution could be to create a custom Exception Class (RedirectException).在这种情况下,解决方案可能是创建自定义异常类 (RedirectException)。

Here you are a link to an interesting post: https://www.trisoft.ro/blog/56-symfony-redirecting-from-outside-the-controller .这是一个有趣帖子的链接: https : //www.trisoft.ro/blog/56-symfony-redirecting-from-outside-the-controller

I know it's debatable, but has sense if it's used within a local function inside its Controller.我知道这是有争议的,但如果在其控制器内的本地函数中使用它是有意义的。

To summarize, the steps would be:总结一下,步骤是:

1) Create a RedirectException class 1)创建一个RedirectException类

2) Create a Kernel Listener 2) 创建内核监听器

3) Set Up the Service in the configuration service file (service.yml) 3)在配置服务文件(service.yml)中设置Service

4) Throw an exception with the url to redirect when necessary. 4)在必要时使用url抛出异常以进行重定向。

This is possible but I would not recommend it.这是可能的,但我不推荐它。 To redirect from service you should provide proper API for you event for example like in: FOSUserBundle where you are receiving instance of FilterUserResponseEvent and you can set response on that event object:要从服务重定向,您应该为您的事件提供适当的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));
    }
}

This is possible thanks to controller:这要归功于控制器:

$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

if (null === $response = $event->getResponse()) {
    // create response
}
// return response from event

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM