@okkkman

Как в Symfony загрузить DTO в Entity?

Всем привет.

Необходимо было отвалидировать данные из DTO и я написал Resolver, который отрабатывает до Controller и взаимодействует с Request. В нем я заинжектил Serializer (для загрузки Request данных в DTO) и Validator интерфейсы соответственно.

Далее мне нужно было DTO загрузить в Entity и при этом учесть вероятность того, что поля между ними могут отличаться.

Для этого написал EntityDtoLoader, своеобразную хурму, которая сверяет существующие set методы и в случае совпадений загружает свои:
protected function load($dto, $model)
{
    $modelMethods = get_class_methods($model);
    $dtoMethods   = get_class_methods($dto);

    foreach ($dtoMethods as $method) {
        preg_match('/get(.*)/', $method, $name);

        if (count($name)) {
            $name = $name[1];

            foreach ($modelMethods as $modelMethod) {
                if ($modelMethod === 'set'.$name) {
                    $model->{'set'.$name}($dto->{'get'.$name}());
                }
            }
        }
    }
}


Минусы у этого решения очевидные.
В общем, лютая дичь.

Обычно люди загружают свою Entity модель из DTO данных ручками, пишут в сервисе "new User" и set'ают данные..

Зря я написал EntityDtoLoader?
Может надо использовать ModelMapper?
Или как лучше?

Можете поделиться вашим подходом? Может у кого есть подходящий репозиторий с примером реализации?

Спасибо
  • Вопрос задан
  • 145 просмотров
Решения вопроса 1
Maksclub
@Maksclub
maksfedorov.ru
Вообще это плохая практика — маппить на сущность дто.

Почему: сущность — некоторый бизнес-обьект, он контролирует переходы состояния и инкапсулирует саму логику. Но сущность находится в контексте... бизнес-процесса, который выражен некоторым др видом классов (интеракторы или use cases, если терминами Боба Мартина), например в CQRS таким родом классов являются хэндлеры команд.
Итог: с сущностями напрямую скорее не стоит работать, тем более в сущностях не должно быть сеттеров :) и методов превращения данных из дто в явном виде ака fromDto(), как указал Flying (при всем моем уважении), тк это не бизнес-логика, а некоторая транспортно-приложенческая... Статические конструкторы могут быть, но не для дто, а для определенных данных, отображающих бизнес-возможность.

Кроме того, ваше решение чревато высокой связанностью — ваши сущности конструируются под дто, дто под сущности...

Как делать хорошо:
Сущности создавать только в рамках бизнес-процесса, то есть всегда явно и напрямую через конструктор или фабричный метод, воплощающий в себе бизнес-логику.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
index0h
@index0h
PHP, Golang. https://github.com/index0h
Зря я написал EntityDtoLoader?

Кто знает, вероятно зря.

Или как лучше?

Сложно сказать, пока что я не совсем понимаю, зачем вам в принципе DTO?
У вас экшн знает какие данные из Request обрабатывать - вытягивайте их явно и проверяйте, да кода больше, но на лонг ране это очень упрощает жизнь, вы явно видите где и что есть.
Дальше, если нужно запихиваете куда нужно.

Есть еще вариант - под каждый экшн сделать отдельный класс *Form / *Message, который на вход получает Request, прям в конструкторе вытягивает данные, валидирует их и запихивает к себе в приватные свойства, преобразовав типы. Наружу предоставляются геттеры.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы