Сериализатор Symfony игнорирует группы сериализации

#php #symfony #serialization #doctrine-orm #symfony4

#php #symfony #сериализация #doctrine-orm #symfony4

Вопрос:

У меня есть объект, поступающий из репозитория Doctrine, который я хочу сериализовать, а затем вернуть обратно. Объект, конечно, имеет несколько отношений, эти отношения также имеют некоторые реальности и так далее. Каждое необходимое отношение уже заполнено, НО НЕ ВСЕ.

Свойства объектов уже имеют некоторые группы сериализации.

 public function getListAction(SerializerInterface $serializer)
{
    // ... Getting data from database with Doctrine
    $entities = $this->someRepository->findByConditions(/* ... */);

    $serializer->serialize($entities, 'json');
}
 

В профилировщике я вижу, что он начинает заполнять остальные отношения. Начинает выполнять запросы к базе данных, чтобы заполнить все недостающие свойства. Затем в конечном итоге время ожидания запроса истекает.

Вопрос: Есть ли способ указать сериализатору только сериализовать данный объект, но не заполнять недостающие отношения? Другими словами, отключить отложенную загрузку?

Добавление новой группы сериализации также было бы нехорошо, потому что у некоторой сущности есть ссылка на саму $parent себя. Так что это снова закончится выполнением запросов.

Ответ №1:

Сериализатор не может увидеть, вызовет ли вызов отложенную загрузку в Doctrine. Вероятно, вы могли бы написать свой собственный нормализатор, который ищет классы из прокси-пространства имен Doctrine, но я полагаю, что это, вероятно, просто станет проблемой, если это решит вашу проблему в первую очередь.

Лучшее решение, которое я могу придумать, — это решить проблему на уровне ORM, поскольку именно это вызывает у вас проблемы.

Например, вы можете создать пользовательский метод поиска в репозитории, используя DQL или QueryBuilder, который будет извлекать все необходимые данные, включая потенциальное объединение связанных объектов, которые вы хотите вывести, и исключая любые поля, которые вам не нужны. Затем я бы увлажнил результат (см. Doctrine Docs: Гидратация), используя Другой гидратор. Вы можете попробовать SimpleObjectHydrator, предоставляемый Doctrine. Насколько я знаю, этот гидратор не будет использовать прокси для отложенной загрузки, а вместо этого будет загружать столько, сколько сможет, и он все равно должен предоставить вам вашу исходную сущность, но быстрая загрузка может быть не тем, что вы хотите. В этом случае вы можете использовать его в качестве ссылки для своего собственного гидратора. Написание пользовательских гидраторов может быть огромной проблемой, и вы могли бы вместо этого выбрать вывод массива и просто полностью отказаться от гидратации объекта. В этом случае вы обязательно потеряете аннотации в своей сущности, которые вам затем нужно будет использовать в своей логике сериализатора.

Вы также можете посмотреть собственные запросы (например, SQL), а затем в качестве альтернативы настроить отображение результирующего набора: см. Doctrine Docs: ResultSetMappingBuilder

Комментарии:

1. Да, прямо сейчас у меня уже есть пользовательский find метод, но я возвращаю сущности обратно увлажненными. Но это на самом деле напомнило: нет смысла их увлажнять. Потому что сразу после того, как я возвращаю их из репозитория, я просто передаю их сериализатору. Если я смогу, я постараюсь не увлажнять их. Пользовательский ResultSetMapping интерфейс также может работать, но структура должна быть такой же. Клиент, вызывающий этот код с использованием SDK, десериализует результат обратно в объекты.

2. Это сработало! Просто извлек результаты getArrayResult , а затем вернул их из контроллера. Отложенная загрузка не запускается таким образом.