Страница 1 из 1

Domain exception mapping

Добавлено: 2017.04.20, 23:33
glagola
Всем привет, у меня из контроллера в контроллер кочует код маппинга исключений домена на исключения Yii.

Пример:

Код: Выделить всё

        try {
            // domain call
            // ...
        } catch (UserNotFoundException $e) {
            throw new ServerErrorHttpException;
        } catch (AdvertisementNotFound $e) {
            throw new NotFoundHttpException;
        } catch (OnlyOwnerCanChangeAdvertisement $e) {
            throw new ForbiddenHttpException;
        }
Большинство таких исключений однозначно мапятся на исключения Yii.

Вопрос - где можно расположить подобный маппинг, чтобы его не писать в каждом action'е? Как это реализованно у вас?

Re: Domain exception mapping

Добавлено: 2017.04.20, 23:43
ElisDN
Например, нследуйте эксепшены от базовых классов и отлавливайте по ним:

Код: Выделить всё

try {
    // domain call
    // ...
} catch (NotFoundException $e) {
    throw new NotFoundHttpException;
} catch (AccessException $e) {
    throw new ForbiddenHttpException;
}

Re: Domain exception mapping

Добавлено: 2017.04.20, 23:52
glagola
Я немного не об этом (хотя спасибо за идею, пригодится). Меня интересует место, где бы можно было расположить маппинг из примера, чтобы с его помощью мапить все исключения во всех контроллерах/экшенах приложения написанного на Yii.

Re: Domain exception mapping

Добавлено: 2017.04.21, 02:23
frostealth
Можно наследовать от базовых классов и расширить yii\web\ErrorHandler

Например

Код: Выделить всё

public function handleException($exception)
{
    if ($exception instanceof NotFoundException) {
        $exception = new NotFoundHttpException();
    } elseif ($exception instanceof AccessException) {
        $exception = new ForbiddenHttpException();
    }

    parent::handleException($exception);
}

Re: Domain exception mapping

Добавлено: 2017.04.21, 02:33
anton_z
Ну если прям все, то можно фабрику исключений, которая по исключению домена будет возвращать исключение Yii. Можно сделать статической, инжектить и засорять конструктор не вижу смысла:

Код: Выделить всё

catch(\DomainException $e) {
	throw UiExceptionFactory::create($e);
}

Но это будет типа GoD класс, знающий обо всех исключения домена.

Re: Domain exception mapping

Добавлено: 2017.04.21, 12:26
glagola
anton_z писал(а): 2017.04.21, 02:33 Но это будет типа GoD класс, знающий обо всех исключения домена.
Согласен, не лучший вариант, поэтому я все-же придерживаюсь, что смапить исключения нужно на территории инфраструктуры. Продолжаю искать варианты.

Re: Domain exception mapping

Добавлено: 2017.04.21, 14:38
glagola
Вообщем, вот к чему я пришел.

Переопределяем компонент errorHandler

Код: Выделить всё

return [
    ...
    'components'          => [
        ...
        'errorHandler' => [
            'class'       => ErrorHandler::class,
            'errorAction' => 'site/error',
        ],
        ...
    ],
    ...
];
Ну и сам класс ErrorHandler:

Код: Выделить всё

class ErrorHandler extends \yii\web\ErrorHandler
{
    protected function renderException($exception)
    {
        try {
            throw $exception;
        } catch (AdvertisementNotFound|ImageNotFound $e) {
            $exception = new NotFoundHttpException;
        } catch (UserBanned|OnlyOwnerCanChangeAdvertisement $e) {
            $exception = new ForbiddenHttpException;
        } catch (UserNotFoundException $e) {
            $exception = new ServerErrorHttpException;
        } catch (\Exception $exception) {}
        
        parent::renderException($exception);
    }
}
Таким образом можно мапить общие ошибки, а если еще воспользоваться идей ElisDN, то этот список замаппленных исключений можно будет сократить.