Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
服务中的重定向-symfony2_Symfony - Fatal编程技术网

服务中的重定向-symfony2

服务中的重定向-symfony2,symfony,Symfony,我可以重定向到服务中的另一个控制器吗 我已经基于提供的示例实现了一个服务 控制器执行的功能代码如下所示: public function verifyanddispatch() { $session = $this->request->getSession(); if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->router->g

我可以重定向到服务中的另一个控制器吗

我已经基于提供的示例实现了一个服务

控制器执行的功能代码如下所示:

 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\u Books\u selected\u Lp”)
为true。尽管如此,我没有被重定向到
app\u listbooks
controller


我认为这是因为我返回的重定向响应不是直接在控制器中,而是在服务中

从架构的角度来看,不应该在服务中创建
重定向响应。一种方法是在服务中抛出异常,该异常在控制器的操作中被捕获,您可以轻松创建
重定向响应


这里可以找到一个例子:

我不知道您是如何定义服务的,但下面的例子很好。假设您正在从控制器调用服务

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(.....);    
    }
}

它似乎使您必须将服务的重定向传递给控制器
RedirectResponse
对象或值,该对象或值将告诉控制器服务中的一切正常,不需要重定向(在下面的示例中为:“true”值)。然后,您必须在控制器中验证提供了哪个值(它是“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;
    }

}

我同意@Moritz的观点,重定向必须在控制器内部完成

但有时,如果从控制器内的本地函数执行某些重定向,则会很有用

在这种情况下,解决方案可以是创建自定义异常类(RedirectException)

这里是一个有趣帖子的链接:

我知道这是有争议的,但如果在控制器内部的本地函数中使用它,这是有意义的

总而言之,这些步骤将是:

1) 创建重定向异常类

2) 创建内核侦听器

3) 在配置服务文件(Service.yml)中设置服务

4) 在必要时引发url异常以重定向


这是可能的,但我不建议这样做。要从服务重定向,您应该为您的事件提供适当的
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));
    }
}
这是可能的,因为控制器:

$checker = $this->get('nobookchoosen_service')->verifyanddispatch();
        if($checker != "true") return  $checker;
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

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

这绝对是清洁的方式。完全同意这是清洁的方式谢谢,我没有在控制器中执行“返回”。控制器a呼叫服务。服务将
RedirectResponse
返回控制器A。控制器A返回
RedirectResponse
,这就是触发实际重定向到控制器B的原因。上面的示例就是这样工作的。有人勇敢地否决了这个答案,但没有足够的人解释原因,以便我们都能知道什么是错的用它!虽然这是可行的,但它可能不是最干净的解决方案。通过返回服务中的重定向响应,您正在创建与SyfOff-HTTP基金会紧密耦合。按照Moritz的建议,最好抛出一个异常,并在控制器甚至异常侦听器中捕获它。这非常有效,但您返回的是一个布尔值,因此您应该检查:if($checker!==true)return$checker;