Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Всем привет. Пишу CRM-систему на Laravel, впервые сталкиваюсь с валидацией большого количества данных. Столкнулся с проблемой при добавлении нового заказа в CRM.
Что необходимо проверять перед добавлением нового заказа:
— Номер телефона. Понятно, что валидацию номера добавляем в StoreOrderRequest.
— Есть ли такой клиент в базе (поиск по номеру). Понятно, что делается Customer::findOrNew().
— Доступен ли в данный момент товар для заказа
— Указан ли адрес доставки (если да, то еще нужно добавить задачу уточнить адрес доставки)
И так далее. Список довольно большой, он будет расширяться по мере разрастания функционала. Но пока что не понимаю, именно с идеологической стороны Laravel, куда именно мне следует запихнуть всю валидацию данных? Понятно, что именно входные данные (Имя клиента, телефон клиента) проверяем в StoreOrderRequest, но куда лучше вынести всю бизнес-логику, как это реализуется?
Есть OrderController, есть public function create(StoreOrderRequest $request){}, но ведь делать контроллер толстым не есть хорошо.
Насколько правильным будет сделать Event нового заказа, а такие параметры, как проверка на ввод адреса доставки, вынести в отдельный Listener и реализовывать бизнес-логику, связанную именно с данным параметром, именно в данном "слушателе"?
Хочется узнать мнение более опытных разработчиков, интересует именно архитектура в данном случае.
Изменено Alexxosipov (01.07.2018 02:18:51)
Не в сети
Я бы не переживал насчет "полноты/толстоты" контроллера. Это только в примерах все выглядит идеально, но реальность другая. Просто смотрите, сможет ли этот код использоваться где-то еще. Если да, то просто создайте вспомогательный класс/метод.
Имхо, события тут не подойдут. Это только запутает код. Гораздо лучше в этом случае иметь хоть и толстый, но достаточно комментированный и структурированный метод в контроллере. Бритва Оккама, короче.
Не в сети
Насколько правильным будет сделать Event нового заказа, а такие параметры, как проверка на ввод адреса доставки, вынести в отдельный Listener и реализовывать бизнес-логику, связанную именно с данным параметром, именно в данном "слушателе"?
Норм. Главное придерживаться одной стилистики кода.
Я, в своих приложениях, разделаю валидацию на "аттрибутную" и "логическую".
Аттрибутная - просто проверяю, что значения валидны и дальнейший код, который с ним работает, не будет падать.
Логическая - уже разлетается по системе. Например проверка свободного номера в отеле. С одной стороны можно просто в реквесте добавить валидацию на признак свободности, но, а если мы хотим вип персонам предоставлять любой номер и выгонять текущих поселенцев? Если расширять валидацию реквеста, то как-то слишком жирно и не гибко.
Так-же бывают случаи, что заранее в реквесте неизвестны какие-то параметры и их нельзя узнать, не прибегая к грязному коду (например супер сложный подсчет скидок машин лернинга, в реквесте дергать какое-то апи скидок для валидации - очень спорно). Поэтому выносить сложную валидацию из реквеста - нормально.
По умолчанию - выноси все в реквест. Как только что-то усложняется, надо думать как логику красиво размазать по системе.
Есть куча разных паттернов, наиболее удачный и правильный вариант - это наиболее удобный для твоего проекта (правда чтобы понять, что будет удобным - нужна какая никакая компетенция в этих вопросах).
Сделай OrderService с методом ->store(...args), в котором и проверяй всю сложную логику. Результат функции либо true, либо Exception (с ошибками валидации или иными ошибками логики).
Не понравится - логику можно будет легко разнести, если точка создания заказа одна (->store()).
Изменено covobo (02.07.2018 11:50:29)
Не в сети
Гораздо лучше в этом случае иметь хоть и толстый, но достаточно комментированный и структурированный метод в контроллере
Больше 10 строк кода (условно) в экшене контроллера - плохо.
Не в сети