#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
, а затем вернул их из контроллера. Отложенная загрузка не запускается таким образом.