Silex: обработчики ошибок для определенных типов исключений - PullRequest
4 голосов
/ 23 марта 2012

Можно ли в Silex использовать обработчик ошибок в зависимости от того, какое исключение выдается?

Я знаю, что это возможно с помощью одного обработчика исключений и оператора switch для имени класса сгенерированного исключения, но мне кажется, что "Silex way" чище, но не работает.

Вот как я ожидал, что это сработает

<?php
// Handle access denied errors
$app->error(function (\App\Rest\Exception\AccessDenied $e) {
    $message = $e->getMessage() ?: 'Access denied!';
    return new Response($message, 403);
});
// Handle Resource not found errors
$app->error(function (\App\Rest\Exception\ResourceNotFound $e) {
    $message = $e->getMessage() ?: 'Resource not found!';
    return new Response($message, 404);
});
// Handle other exception as 500 errors
$app->error(function (\Exception $e, $code) {
    return new Response($e->getMessage(), $code);
});

Проблема в том, что, когда я генерирую исключение ResourceNotFound в моем контроллере, выполняется обработчик ошибок, связанный с AccessDenied

Исправляемая фатальная ошибка: аргумент 1, передаваемый в {closure} (), должен быть экземпляром App \ Rest \ Exception \ AccessDenied, экземпляром App \ Rest \ Exception \ ResourceNotFound с указанием

Это достижимо по-другому, или я должен просто вставить все в обработчик, который работает с общими исключениями, и включить тип создаваемого исключения?

PS: я знаю о методе $app->abort(), но предпочитаю работать с исключениями

Ответы [ 2 ]

5 голосов
/ 25 марта 2012

РЕДАКТИРОВАТЬ: Эта функция теперь включена в ядро ​​Silex!


В настоящее время это невозможно.Прямо сейчас у вас должен быть либо один обработчик с оператором switch, либо множество обработчиков с if ($e instanceof MyException) каждый.

Мне действительно нравится эта идея, и должна быть возможность реализовать ее с помощьюотражение.Было бы здорово, если бы вы могли создать новый билет на трекере или даже поработать над патчем, если вам интересно.

Cheers!

0 голосов
/ 27 апреля 2012

Другое решение, которое я использую в своих проектах:

class ProcessCallbackException extends Exception
{
    public function __construct(\Closure $callback, $message = "", Exception $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->callback = $callback;
    }

    public $callback;
}

class AccessDeniedException extends ProcessCallbackException
{
    public function __construct($message = null)
    {
        $f = function() {
            return app()->redirect('/login');
        };

        parent::__construct($f, $message);
    }
}

# Handle your special errors
$app->error(function (\Exception $e, $code) {
    if ($e instanceof ProcessCallbackException)
    {
        /** @var ProcessCallbackException $callbackException */
        $callbackException = $e;
        return call_user_func($callbackException->callback);
    }
    else
        return null;
});
...