API с выборкой по многим параметрам, которые идентичны - нужно писать 2 контроллера копии? Или допустимо в API вызвать контроллер web?
Или вообще нужно метод в модели для выбора по многим условиям?
Эта модель должна билдер возвращать или результирующий массив?
в сервис вынеси код
если речь идет о фильтрации, то присмотрись к tucker_eric eloquent filter
спасибо, получается в контроллере будет валидация, а сервис уже предполагает что данные проверены, или как?
или типа if isset or !empty ... add parameter
не всё так просто/однозначно. валидация запроса и валидиация данных в сервисе могут быть разными. Можешь здесь немного почитать: https://github.com/adelf/acwa_book_ru/blob/master/manuscript/6-validation.md
опять Аделя книга, никак не доберусь до нее) спасибо, изучаю)
один из ходового варианта - передавать в сервис DTO который содержит валидные данные
А что лучше использовать DTO или ресурсы? которые вот эти https://laravel.com/docs/10.x/eloquent-resources
DTO это паттерн, общее названия классов для передачи данных между подсистемами, применение широкое. апи ресурсы ларки, согласно их же доке, что ты скинул: When building an API, you may need a transformation layer that sits between your Eloquent models and the JSON responses that are actually returned to your application's users. имеют более конкретное предназначение, а именно ответ апишки. в целом апи ресурс это и есть dto
Ну просто у DTO же ещё формат данных можно указать и маленько не разобрался как быть с данными которые опциональные, которые могут придти, а могут и нет, а у ресурса обычный массив
не оч понял о каком формате речь? dto - простой класс, без логики, содержащий явные данные. может содержать как простые типы, так и другие dto. поля могут быть опциональными, чаще всего readonly, но не обязательно
а чем DTO от Value Object отличается?
VO содержит только 1 значение. DTO - поля и свойство. VO - только свойство.
О форматах полей ну там public string $name; А потом $this->name = 'name'; Просто если не придёт то никакого string поле не получит, в этом моменте и не понимаю как сделать
Интересно не совсем понятно , для чего нам выносить валидация из контролёру в другие сервисы ? Доп слой создавать
ну у тебя DTO имеет строгое содержание. если у тебя свойство опционально, то public ?string $name = null иначе у тебя не хватает данных, а это должно быть проверено до попытки создать DTO. ну кто-то не согласится и скажет, что он валидирует в DTO, но мое мнение, что это не правильно, дто не должно содержать доп. логики, максимум оно может содержать статические правила для валидации своих полей.
Спасибо, а если так напишу, то потом же как то надо вычищать все null из объекта, чтобы не болтались. Или случайно их в базу не записать, где есть nullable поле при обновлении.
в контроллере, в ларке, используем FormRequest - валидируем входящие данные в запросе и обрабатываем ошибки для пользователей. дальше используем входящие данные как валидные. но, не в контроллере мы же пишем саму логику, и это называется сервисным слоем - классы которые что-либо делают конкретное, решают бизнес-задачи. И мы передаем эти данные в какой-то класс (сервис, экшен, команду, таск). И здесь вопрос - как мы можем доверять данным переданным в сервис, внутри сервиса? Вдруг кто-то вызовет этот сервис где-то еще и вручную передаст данные, или не провалидирует их? У Аделя эта проблема вроде норм расписана, если не вник, попробуй перечитать, на практике пописать. Если кратко, то дто гарантирует что внутри сервиса мы работаем с конкретными и валидными данными, например: $data = [user_id => 1, status => 0]; // какой-то массив данных из запроса $service->handle($data); pubf handle(array $data) { $data['user_id'] // мы не уверены, что существует такой ключ в массиве, мы вообще не уверены о содержимом $data, кроме того что это массив, но массив чего мы не знаем никогда и это придется всё проверять. } pubf handle(AnyDto $data) { $data->user_id; // мы точно знаем что у AnyDto есть свойство user_id и что оно int. }
ну это не связанные с DTO моменты. как тебе надо так и используй. если ты про то что $model->update($dto->all()); то такое се. но, конечно, ты можешь сделать базовый дто или трейт, где будет метод toArray() и любой другой, например, $dto->excludeEmpty() (название не очень), хотя такое на практике мне не нужно было, возможно, просто достаточно немного свой код пересмотреть. тут вопрос такой: почему null тебе надо исключить? а если null надо записать в бд?
array_filter($dto->toArray());
Если я правильно понял суть разговора, то я иногда в самой дтошке пишу метод toModelData():array и возвращаю массив, который можно передать в Model::create($dto->toModelData()). Конечно немного противоречит сути дто, но весьма удобно. В принципе ничего не мешает сделать этот метод и в самом сервисе приватным методом.
Вот как раз так и делаю что update и весь dto, а как правильно делать, тоже по полям указывать? При обновлении точно нигде не требуется записать, при создании nullable поле само запишет null если его нет. Почему исключить надо, потому что с разных мест разные данные приходят, а так как таблица одна, то и dto общее
VO - это такой способ обыграть несуществующие в языке типы данных. например: Email, номер телефона, координаты, валюта. так наверное будет правильнее, я там выше сказал, что одно свойство, скорее логическое свойство. т.е. если говорить про координаты, то будет два поля - широта и долгота.
да, норм, если не вызывает проблем.
Если противоречит тогда не, не подходит
ну если у тебя есть поле phone nullable. если ты не передал его в запросе - его не надо обновлять, если передал null, то его надо удалить, т.е. записать в null. т.е. по разному можно трактовать
Всё, ещё больше запутался, как то не учёл такие случаи, когда действительно надо будет убрать
как делают: - передают всегда все данные и обновляют их, даже если они не изменились - передают только те данные которые надо изменить - добавляют в запросы флаги для очистки (обычно используется, когда надо удалить файлы), т.е. например аватарку можно загрузить новую и она заменит старую, а можно просто удалить, а можно ничего не менять, но при этом отправлять форму для изменения имени и других данных.
первый вариант в скоупе с ёлкой - норм. просто, жирно, не напряжно
Спасибо большое тогда добавлю флаги и буду по ним определять надо ли в базу писать или нет
ну это ближе к костылю. в чем проблема отправлять только те данные, которые ты хочешь изменить?
Потому что как ранее сказал DTO общее, вот например в одной форме пароль меняется с проверкой старого, в другой форме имя пользователя, отправляются получается разные данные, а DTO одно потому эта сущность пользователя, поменяю тоже имя, пароль в таком случае необязательным полем становится, а значит получит null, в этом и проблема возникает, что мне его не надо трогать и наоборот когда меняю пароль, имя необязательное
Если всем сделаю public ?string $name; public ?string $password; То тоже будет похоже на костыль
ну пароль - да, можно фильтровать, у тебя скорей всего не может быть такого, что пароль будет null, следовательно, если его нет, то он не изменяется. для остальных полей надо рассматривать варианты. иногда еще делают (в ларке можно тоже такое найти), как вместо null вешается какой-то класс, например Empty, т.е. можно так обыграть, что все поля содержащие этот тип данных - должны быть очищены. а null - отфильтрованы и не изменяться. Но надо на месте смотреть. другой варик - разные DTO, разные сервисные методы/классы.
блин когда читаешь это всё, понимаешь что вообще неправильно всё делал.....
С классом да какие-то решения встречал, когда свой вопрос гуглил до того как сюда написать, тоже попробую, ещё раз спасибо
да, это ощущение не проходит ))) всегда есть за и против любого решения.
Точно , спасибо за разъяснение
Обсуждают сегодня