Comments 19
В нашей API каждый запрос обрабатывается с помощью модели
Зачем же вам контроллер, если запрос моделью обрабатывается?
Имеется ввиду, что все входные данные читаются не напрямую, а через модель. Это отсекает все лишние проверки, вся бизнес логика построена уже на основе «чистых» данных из модели.
Тобишь фильтры в модели?
Если совсем грубо говоря, то да.
На самом деле фильтрация происходит на разных уровнях:
1) JSON, который приходит в body конвертируется в привычный для Symfony вид, например вот так https://github.com/FriendsOfSymfony/FOSRestBundle/blob/2.0/EventListener/BodyListener.php
Грубо говоря на выходе мы получаем ассоциативный массив
2) В дело вступает первая прослойка data mapper`а: каждое значение этого массива приводится к ожидаемому виду, будь то строка, число, массив или что-то более сложное.
3) Модель получает ВСЕГДА ожидаемое значение, если ожидается строка, а прислали массив – до модели оно не дойдет, отскочит с эксепшеном уровнем выше. Можно сказать, что данные, которые приходят в модель – уже относительно чистые. По-сути data mapper это замена формам.
А дальше модель валидируется на основе Constraint`ов записаных в ней, в случае ошибки – так же улетает эксепшен
После всех этих шагов – мы спокойно работаем с моделью, которая внутри себя содержит все необходимые данные и они нам точно подходят
На самом деле фильтрация происходит на разных уровнях:
1) JSON, который приходит в body конвертируется в привычный для Symfony вид, например вот так https://github.com/FriendsOfSymfony/FOSRestBundle/blob/2.0/EventListener/BodyListener.php
Грубо говоря на выходе мы получаем ассоциативный массив
2) В дело вступает первая прослойка data mapper`а: каждое значение этого массива приводится к ожидаемому виду, будь то строка, число, массив или что-то более сложное.
3) Модель получает ВСЕГДА ожидаемое значение, если ожидается строка, а прислали массив – до модели оно не дойдет, отскочит с эксепшеном уровнем выше. Можно сказать, что данные, которые приходят в модель – уже относительно чистые. По-сути data mapper это замена формам.
А дальше модель валидируется на основе Constraint`ов записаных в ней, в случае ошибки – так же улетает эксепшен
После всех этих шагов – мы спокойно работаем с моделью, которая внутри себя содержит все необходимые данные и они нам точно подходят
А почему не вынести обработку в сервисы, SOA-way?
Обработку чего именно? Вся бизнес логика внутри сервисов, data-mapper тоже сервис, так что нет разницы где и как его использовать
Но что-то мне подсказывает что сущности анемичны.
Извиняюсь за возможно глупый вопрос, но не могли бы вы объяснить значение этого медицинского термина в данном контексте?
Это когда наши сущности это не полноценные объекты с поведением, а тупые структуры из геттеров и сеттеров. [AnemicDomainModel]
Сталкивался с этой задачей. Пришлось крутить свой велосипед: https://github.com/leoza/entities-bundle
Рекомендую к просмотру: Marco Pivetta — Doctrine ORM Good Practices and Tricks
symfony.com/doc/current/components/serializer.html как альтернатива data_mapper.
Много чего перепробовал (формы, сериализацию, чистые данные)
Везде есть минусы. Если API нагружено хоть немного то формы и сериализаторы сильно негативно влияют на производительность.
Я остановился на DTO который создается из request с помощью OptionsResolver
В DTO описывают параметры и валидация.
1. Реквест преобразуется в DTO
2. В сервис бизнес логики передается DTO (Тайп хинтинг появляется :) )
3. Сервис возвращает данные которые передаются в Formatter
4. Форматированные данные уходят на респонс
Везде есть минусы. Если API нагружено хоть немного то формы и сериализаторы сильно негативно влияют на производительность.
Я остановился на DTO который создается из request с помощью OptionsResolver
В DTO описывают параметры и валидация.
1. Реквест преобразуется в DTO
2. В сервис бизнес логики передается DTO (Тайп хинтинг появляется :) )
3. Сервис возвращает данные которые передаются в Formatter
4. Форматированные данные уходят на респонс
В статье примерно тоже самое
ну чтож, осталось переименовать DTO запросов в команды, сделать для каждой команды отдельные сервисы-хэндлеры, которые не возвращают ничего, и отдельные сервисы которые получают нужное состояние. И получится почти CQRS.
p.s. сам так же делал еще относительно недавно, сейчас все больше и больше нравится подход полного разделения ответственности на чтение и запись. Такой код выходит проще всего поддерживать.
p.s. сам так же делал еще относительно недавно, сейчас все больше и больше нравится подход полного разделения ответственности на чтение и запись. Такой код выходит проще всего поддерживать.
Sign up to leave a comment.
Symfony: обработка запросов в API