Domain exception mapping

Обсуждаем, как правильно строить приложения
Ответить
glagola
Сообщения: 47
Зарегистрирован: 2017.02.22, 19:43

Domain exception mapping

Сообщение glagola » 2017.04.20, 23:33

Всем привет, у меня из контроллера в контроллер кочует код маппинга исключений домена на исключения Yii.

Пример:

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

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

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

Аватара пользователя
ElisDN
Сообщения: 4466
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Domain exception mapping

Сообщение ElisDN » 2017.04.20, 23:43

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

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

try {
    // domain call
    // ...
} catch (NotFoundException $e) {
    throw new NotFoundHttpException;
} catch (AccessException $e) {
    throw new ForbiddenHttpException;
}
Не забудьте пройти мастер-класс по Yii2.

glagola
Сообщения: 47
Зарегистрирован: 2017.02.22, 19:43

Re: Domain exception mapping

Сообщение glagola » 2017.04.20, 23:52

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

frostealth
Сообщения: 6
Зарегистрирован: 2017.03.31, 20:07

Re: Domain exception mapping

Сообщение frostealth » 2017.04.21, 02:23

Можно наследовать от базовых классов и расширить yii\web\ErrorHandler

Например

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

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

    parent::handleException($exception);
}

anton_z
Сообщения: 218
Зарегистрирован: 2017.01.15, 15:01

Re: Domain exception mapping

Сообщение anton_z » 2017.04.21, 02:33

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

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

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

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

glagola
Сообщения: 47
Зарегистрирован: 2017.02.22, 19:43

Re: Domain exception mapping

Сообщение glagola » 2017.04.21, 12:26

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

glagola
Сообщения: 47
Зарегистрирован: 2017.02.22, 19:43

Re: Domain exception mapping

Сообщение glagola » 2017.04.21, 14:38

Вообщем, вот к чему я пришел.

Переопределяем компонент 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, то этот список замаппленных исключений можно будет сократить.

Ответить