Pull to refresh

Symfony2 перехватчик исключений с помощью сервисов или как избежать использования Event Listener

Symfony *
Sandbox
Сегодня я хочу поделиться своим скромным опытом и показать, как можно сделать перехватчик исключений, не используя Event Listener. Но сначала пару слов о том, зачем это нужно.

Я считаю, что использование Event Listener'ов в обычном приложении делает код запутанным, к тому же многие неопытные разработчики злоупотребляют данным подходом (сам так делал). А вот использование сервисов делает код понятным, так как они вызываются в том месте, в котором объявлены. И как вы уже поняли, далее речь пойдет именно о сервисах.

Итак, начнем.

Сначала переопределим ExceptionController, о чем скромно намекает официальная документация:

namespace AppBundle\Controller;

use Symfony\Bundle\TwigBundle\Controller\ExceptionController as Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use AppBundle\Exception\ExceptionHandler;

class ExceptionController extends Controller
{
    public function __construct(ExceptionHandler $handler) 
    {
        $this->handler = $handler;
    }

    public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
    {
        $message = $this->handler->handle($exception)->getMessage();

        return new JsonResponse(array(
            'message' => $message
        ));
    }

}

Далее создадим сервис, который занимается обработкой исключений:

namespace AppBundle\Exception;

use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class ExceptionHandler
{
    private $message = null;

    public function handle($exception)
    {
        switch($exception->getClass()) {
            case 'Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException' :
                $this->message = "Need full authentication";
                break;
            case 'Symfony\Component\Security\Core\Exception\AccessDeniedException':
                $this->message = "Access Denied";
                break;
            /**
            * Указываем действия для всех нужных исключений
            **/
            default:
                break;
        }

        return $this;
    }

    public function getMessage()
    {
        return $this->message;
    }
}

Теперь регистрируем наш сервис:

# services.yml
app_bundle.exception.handler:
    class: AppBundle\Exception\ExceptionHandler


Далее регистрируем наш контроллер как сервис(не забываем передать в него Exception Handler):

# services.yml
app_bundle.exception.controller:
    class: AppBundle\Controller\ExceptionController
    arguments:
        - @app_bundle.exception.handler

Осталось самое главное: указать в config.yml, что исключения обрабатывает именно наш контроллер:

# config.yml
# Twig Configuration
twig:
    exception_controller: app_bundle.exception.controller:showAction

Надеюсь на вашу конструктивную критику, а также на то, что для кого-то эта статья окажется полезной.
Tags: symfony2
Hubs: Symfony
Total votes 14: ↑12 and ↓2 +10
Comments 20
Comments Comments 20