Redirecting in service - symfony2

前端 未结 5 475
南方客
南方客 2021-01-17 22:03

May I perform redirection to another controller within service?

I have implemented a service based on example provided by @Artamiel.

My function code which i

相关标签:
5条回答
  • 2021-01-17 22:43

    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:

    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
    
    0 讨论(0)
  • 2021-01-17 22:44

    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

    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.

    // 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(.....);    
        }
    }
    
    0 讨论(0)
  • 2021-01-17 22:44

    From an architecture point of view one should not create a RedirectResponse in a service. 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.

    An example can be found here: Redirect from a Service in Symfony2

    0 讨论(0)
  • 2021-01-17 22:50

    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). 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.

    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;
    
    0 讨论(0)
  • 2021-01-17 22:54

    I am agree with @Moritz that redirections must be done inside controllers.

    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).

    Here you are a link to an interesting post: 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

    2) Create a Kernel Listener

    3) Set Up the Service in the configuration service file (service.yml)

    4) Throw an exception with the url to redirect when necessary.

    0 讨论(0)
提交回复
热议问题