Reputation: 165
I have an action which takes an argument, the route looks like this:
/cs/{id}
It's the individualAction
in the Cassette
controller.
Sometimes, there's an exception 500 Internal Server Error - NoResultException
- this is expected behaviour.
I am looking to redirect to another controller action, editAction
, when this happens, the route is as such:
/cs/{id}/edit
It needs to be controller-specific, since I want to repeat this with different controller actions. It also needs to keep the argument from the original action.
I've been looking into event listeners, but I'm not sure if that's overkill and I'm struggling to find out how to make them action-specific - I'm happy to keep the code in the controller if that's the better solution.
Upvotes: 4
Views: 1571
Reputation: 13167
An EventListener
is the most appropriated to change the comportment of your app when an exception is thrown.
Use something like :
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Routing\RouterInterface;
use Doctrine\ORM\NoResultException;
class ExceptionResponseListener
{
public function __construct(RouterInterface $router)
{
$this->router = $router;
}
/**
* @param GetResponseForExceptionEvent $event
*/
public function onKernelResponse(GetResponseForExceptionEvent $event)
{
$request = $event->getRequest();
$routeName = $request->get('_route');
$exception = $event->getException();
// Restrict the route by adding a check on the route name
// Or a pattern of route names (!strpos($routeName, '_show'))
// Or for many routes: (!in_array($routeName, ['xxx_show', ...]
// Or the _controller: $request->get('_controller')
// Output something like: "AcmeBundle\\Controller\\DefaultController::showAction"
if ('expected_route_name' !== $routeName) {
return;
}
// Retrieve your param
$params = $request->get('_route_params');
if ($exception instanceof NoResultException) {
// Create a redirection to the edit route
$response = new RedirectResponse(
$this->router->generate('your_edit_route', array('id' => $params['id']))
);
$event->setResponse($response);
}
}
}
And register it as service :
services:
# ...
acme.kernel.listener.exception_listener:
class: AppBundle\EventListener\ExceptionResponseListener
tags:
- {name: kernel.event_listener, event: kernel.exception, method: onKernelResponse}
arguments: ['@router']
Another simple alternative could be to make a forward/redirection of the expected action directly in your method, instead of throw the exception.
Upvotes: 1