@hell0w0rd, взгляд неплохо бы аргументировать, а то у нас все эксперты в политике, футболе и медицине, кроме, соответственно, политиков, футболистов и врачей
Я не думаю, что такое есть из коробки, но вроде это несложно делается. Нужно повесить на событие GetResponseForExceptionEvent штуку, которая по типу исключения достанет метаинформацию из конфига об HTTP-статусе, возможном обработчике и т.д.> разнести этот mapping по конфигам, аннотациям.
а симфони умеет по аннотациям передать exception в соответствующий обработчик?
Чем же это лучше? У тебя в каждом action'е будет такой код. А если ты попытаешься указывать конкретный тип исключения, то ты столкнешься с проблемами, которые я описал выше.Гм. Ошибка улетает куда-то и кто-то ее обрабатыает, это работает не явно.
вот так лучше. Понятно где и что происходит.Код:try { ... } catch (e) { return new ErrorResponse(e); }
Есть такой принцип. Single Responsibility называется. Controller just controls the request processing flow. Обработка ошибок не его забота. Это забота, как ни странно, товарища по имени Error Handler. Не люблю все эти слова mvc hmvc... юзайте SRP и будет легко и приятно, имхо. И Laravel я люблю именно за то, что он легок для следования SRP.Мне сам подход не нравится, когда ошибки улетают куда-то за пределы контроллера.
Помоему, ты процедурно мыслишь немного. В самом простейшем случае у Exception есть message. В случаях посложнее можно ClientNotFoundException, etc. насоздавать. и там по соглашениям, ключи для локализированного вывода ошибок. Или если уж совсем не вмешивать в модель такую инфу, да - делай маппинг вроде - ClientNotFoundException -> client_not_found -> локализация сообщения и вывод. Это лишь только вариант. Возможностей много.@Adelf, а если типов entity много? Т.е. не только Client как в примере, и для всех надо выдавать осмысленное сообщение об ошибке, например, надо вывести не "Запись не найдена", а "Пользователь не найден", "Товар не найден" и т.д.? В таких случаях все перехватывать в одном месте для всех типов?
"Явное лучше, чем неявное." Уже было. Однако, развитие программирования всегда идет по пути роста уровней абстракции.Гм. Ошибка улетает куда-то и кто-то ее обрабатыает, это работает не явно.
try catch лучше. Понятно где и что происходит.
Принцип SRP является частным случаем Бритвы Оккама, и рассматривать его надо в контексте, не противоречащем основному правилу.Есть такой принцип. Single Responsibility называется. Controller just controls the request processing flow. Обработка ошибок не его забота. Это забота, как ни странно, товарища по имени Error Handler. Не люблю все эти слова mvc hmvc... юзайте SRP и будет легко и приятно, имхо. И Laravel я люблю именно за то, что он легок для следования SRP.
А ты это решал как-то на уровне контроллеров? Проще, например, добавить флаг к параметрам нужных route'ов: если есть флаг и без «/» на конце, то редирект.Пример моей реальной задачи, которую я решал осенью. В проекте приняли новый стандарт, по которому часть url на сайте должны стать с / в конце, а часть - без. Соответственно, весь трафик по проиндексированным вразнобой url надо было редиректить к стандартным. Единый exception здесь был бы как корове седло.
"Хотя на самом деле решения равноправны и сравниваться должны практикой."В твоем случае выводы не совсем корректны.
public function postUpdate(\Request $request, $id)
{
$client = Client::find($id);
if(!$client) {
abort(404, 'Client not found');
}
$this->authorize('manage', $client);
// И то я не сомневаюсь, что наверняка
// прям тут стали бы проверять права вручную,
// без помощи ларавелевского authorize, где
// правила авторизации описаны отдельно в своем провайдере или Policies
$validator = \Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
// много много строк...
// и конечно среди них будут правила валидации типа not_exists и unique
// которые сами залезут в базу и посмотрят все что надо
]);
if ($validator->fails()) {
return redirect()//->action or route...
->withErrors($validator)
->withInput();
}
$client->fill($request->all());
return redirect()->...;
}
Вот это вообще контроллеров не касается Как Вурдалак уже заметил это проблема роутинга.Пример моей реальной задачи, которую я решал осенью. В проекте приняли новый стандарт, по которому часть url на сайте должны стать с / в конце, а часть - без. Соответственно, весь трафик по проиндексированным вразнобой url надо было редиректить к стандартным. Единый exception здесь был бы как корове седло.
То, что я не согласен с твоим решением, не значит, что я предпочитаю try-catch как у @hell0w0rd.Перепишу свой метод так, как описывается в мануалах по ларавель.
Разносить по классам как в моем примере довольно дорого по времени. Но, мне кажется, даст большой выигрыш в дальнейшей поддержке.
Например, были url вида zzz.domain.tld/title/, и оказалось, что при смене title внезапно теряется трафик на проиндексированные url.
Нужно все перевести на domain.tld/zzz/title.123.html, где 123 - id сущности.
Чтобы получить 123 надо сходить в базу, это уже логика приложения.
Так вот перед тем как выкинуть 404 контроллер должен определить что это старый формат, проверить zzz и по title узнать 123. Причем, для некорректного zzz надо выдавать одну ошибку, для несуществующего title - другую. Делать 2 редиректа сначала для zzz, потом для 123 нельзя - гугл против.
И тут со стройной логикой получается хрень.
Твой кейс не противоречит его подходу, просто нужно было бы написатьТвой подход красивый на бумаге, да забыли про овраги - когда придется менять поведение для части случаев, проброс исключений из модели напрямую в error handler не позволит обработать контекст, который находится в ведении контроллера.
public function actionGetArticle($id, $title) {
$articleDto = $this->articleQueryService->get($id);
if ($articleDto->getTitle() !== $title) {
return redirect()->route('_article', ['id' => $id, 'title' => $articleDto->getTitle()]);
}
// ...
}
if ($articleDto->getTitle() !== $title) - и я об этом жеМои контроллеры устроены иначе. В них заложен только один сценарий - когда все хорошо. Если что-то плохо - где-то кидается исключение и система знает что ответить юзеру. Код в разы более чистый
...
Controller just controls the request processing flow. Обработка ошибок не его забота. Это забота, как ни странно, товарища по имени Error Handler.