Тема: Связать три таблицы Doctrine ORM

Здравствуйте, я никогда не работал  работал с Doctrine ORM, поэтому прошу помощи, такой вот встал вопрос у меня есть 3 таблицы продукты категории и таблица которая связывает их, необходимо как-то сгенерировать или описать правильные модели, чтобы с ними дальше работать вся беда в том что во всех примерах (и в документации в том числе) связи описываются только между двумя таблицами, но вот как при этом задействовать 3 таблицы никак не могу понять, точнее есть некоторые соображения, но боюсь что получаться костыли, подскажите в каком направлении двигаться, какие лучшие практики использования Doctrine для таких задач

2

Re: Связать три таблицы Doctrine ORM

Связь many-to-many это всегда три таблицы. Просто связующая таблица никак не описывается, ее менеджмент — вопрос ORM. Вы описываете только модели в контексте PHP, и в них никакой самостоятельной связующей сущности (в простейшем случае) нет.

Вы, разумеется, также можете описать many-to-many как две связи one-to-many, и тогда у вас будет связующая сущность в PHP также. Такое бывает нужно, когда связь содержит собственные дополнительные поля, аля время создания связи или любые другие атрибуты, требуемые бизнес-логикой.

3 Отредактировано vova.sarckisyan (2016-07-08 20:09:54)

Re: Связать три таблицы Doctrine ORM

relo_san пишет:

Связь many-to-many это всегда три таблицы. Просто связующая таблица никак не описывается, ее менеджмент — вопрос ORM. Вы описываете только модели в контексте PHP, и в них никакой самостоятельной связующей сущности (в простейшем случае) нет.

Вы, разумеется, также можете описать many-to-many как две связи one-to-many, и тогда у вас будет связующая сущность в PHP также. Такое бывает нужно, когда связь содержит собственные дополнительные поля, аля время создания связи или любые другие атрибуты, требуемые бизнес-логикой.

Спасибо большое за ответ так и сделал все работает!! но вот появился такой момент, при такой связи я к примеру создаю объект категории и далее пытаюсь получить все продукты этой категории, и получается у меня в  классе Category есть свойство  Products, которое хранит в себе экземпляр класса ArrayCollection и при вызове getProducts() для каждого продукта создается новый запрос в БД это нормальная  практика для Doctrine? или же лучше в классах писать свои методы с использованием DQL например.

4

Re: Связать три таблицы Doctrine ORM

vova.sarckisyan пишет:

и при вызове getProducts() для каждого продукта создается новый запрос в БД это нормальная  практика для Doctrine?

Нормальная. Доктрина же не в курсе, что вам нужны эти товары, чтобы заранее их получить одним запросом. Метод getProducts() просто возвращает вам ту самую коллекцию с пустыми прилинкованными объектами, содержащими только идентификаторы. А дальше уже при обращении к такому пустому объекту происходит его инициализация и заполнение данными, через отдельный запрос разумеется. Это плата за простоту. Но в реальной жизни так никто не делает. default/smile

Вам нужна категория с товарами? Создайте в репозитарии отдельный запрос, который выгребает не только категорию, но и ее товары через join. Если все нужные данные будут получены сразу, то никаких повторных запросов не будет. Исключение составляет поиск по условиям, он не может учитывать уже полученные ранее объекты, так как заранее неизвестно, какие объекты войдут в результат и есть ли они в кеше из предыдущих выборок.
Это, разумеется, не конкретное предложение для решения задачи, а стратегия. Если у вас в категории 100500 товаров, то вы не будете их все выгребать через джойн сразу в коллекцию. Но в таком случае вам и метод getProducts() вообще не нужен, вам нужна отдельная выборка с учетом постраничного вывода, а следовательно все тот же репозитарий и отдельный запрос, получающий все нужные товары.

Re: Связать три таблицы Doctrine ORM

relo_san пишет:

[quote=vova.sarckisyan пишет:
Но в реальной жизни так никто не делает. .

Ну в общем я примерно так и думал, просто надо было мнение профессионала,  спасибо большое что показали правильное направление, интересный symfony фреймворк думаю подсяду на него надолго, хотя доктрину все же считаю в некоторых моментах не совсем удобной по сравнению с ActiveRecord, например, но не исключено что это из-за незнания всех возможностей этой ORM

6

Re: Связать три таблицы Doctrine ORM

vova.sarckisyan пишет:

хотя доктрину все же считаю в некоторых моментах не совсем удобной по сравнению с ActiveRecord

Удобство — штука относительная и скорее вопрос привычки.
После Доктрины я на ActiveRecord смотрю как на говно. При этом я саму Доктрину (как ORM) использую не везде — в выборках, особенно если важна производительность, полноценный и тяжелый ORM не нужен, его фичи все равно не используются, DBAL'а + гидрации достаточно. ORM удобен именно в управлении данными.

У ActiveRecord есть куча минусов и весьма мало плюсов. Плюс по сути один — простота. Объект сам себя сохраняет. Можно взять объект из любого места, что-то в нем поменять и сохранить. Это же по совместительству и огромный недостаток — нет никакого контроля доступа к изменению, изменение объекта размазывается по приложению. В результате какой-нибудь User может сохраняться в разных точках пять раз за один цикл выполнения приложения. Сущность в ActiveRecord из-за необходимости уметь себя сохранять должна содержать кучу управляющей логики и валидацию, что делает ее тяжелой. При этом, если «что-то пошло не так», то сущность не может ничего, кроме как выбросить исключение, которое никто ловить не будет — отказоустойчивые стратегии вычеркиваем. С валидацией все сложно, особенно если оная зависит от других сущностей. Вообще предполагается, что валидация должна быть внешней, но нет никакого контроля ее использования, все отдается на откуп программисту. Причем не тому программисту, который писал сущность User'а, а тому, который будет эту сущность где-то в этом приложении сохранять. Это далеко не полный перечень проблем — на сложных сценариях, где задействованы десятки связанных сущностей, есть сложная бизнес-логика и источник данных не один, все намного более грустно.

У Доктрины конечно тоже есть свои тараканы. Например, незнающий её фичи программист может где-то что-то поменять в сущности, не сохраняя. А потом в совершенно другом месте какой-то посторонний код при сохранении другой сущности вызовет flash() и программист будет удивляться, что сущность все равно сохранилась. Еще хуже, если первая сущность не прошла валидацию — она все равно будет сохранена. Это минус дизайна Доктрины и неопытные на него натыкаются. Но плюсов у Доктрины гораздо больше, как и фич. И главное — она более гибкая, ее минусы при желании вполне спокойно обходятся и нейтрализуются, чего не скажешь про ActiveRecord.