@sadCake

Как заставить доктрину увидеть поля в jointable?

Есть 2 сущности. City и Service.
В Service:
/**
     * @var ArrayCollection
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\City", inversedBy="services")
     * @ORM\JoinTable(
     *     name="city_service_rel",
     *     joinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="id", onDelete="CASCADE")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="city_id", referencedColumnName="id", onDelete="CASCADE")}
     * )
     */
    protected $cities;

В City:

/**
     * @var ArrayCollection
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\City", mappedBy="cities")
     */
    protected $services;


Пытаюсь через query builder написать запрос, чтобы получить все сервисы, которые есть в определенном городе.

$qb = $this->createQueryBuilder('service');

        $qb
            ->where('service.active = true')
            ->andWhere($qb->expr()->isNotNull('service.representative'))
            ->innerJoin(
                'service.cities',
                'cities',
                'WITH',
                'cities.city_id = :id'
            )
            ->setParameter('id', $cityId)
        ;


В итоге доктрина не может найти связанные колонки, а если заджойнить service.cities, то он пытается найти какие-то свойства в классе City.
  • Вопрос задан
  • 61 просмотр
Решения вопроса 1
passionkillah
@passionkillah
Backend-разработчик
У вас маппинги уже настроены таким образом, что вы можете просто достать нужный город и через геттер получить коллекцию сервисов, которые в нем есть - доктрина все сделает за вас.

Что касается запроса, он не совсем корректен. Во-первых, вы подставляете параметр не туда, куда необходимо: последний параметр в innerJoin'е отвечает за то, по какому параметру соединять две сущности. Во-вторых, вы обращаетесь к city_id при том, что делаете запрос не на SQL, а на DQL - то есть по сути во время выполнения этого запроса вы присоединяете не таблицу, а коллекцию объектов. На этом уровне доктрина не в курсе ни о каком city_id. В-третьих, доктрина при присоединении коллекции понимает, что речь идет о many-to-many - соответственно, последние два параметра при join'е можно опустить:
->join('service.cities', 'city')
->andWhere('city.id = :id')
->setParameter('id', $id)

Работая с доктриной, следует немного поменять мышление: стоит абстрагироваться от бд и думать о сущностях как об обычных объектах. Надеюсь, что мне удалось корректно сформулировать ответ.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы