Доктрина: ВЫБЕРИТЕ связанную сущность

У меня есть 2 сущности:

  • LinkServInfra
  • Серв

Объект LinkServInfra:

  • id
  • serv (отношение OneToOne к Serv)
  • инфра (ManyToOne к другому объекту)

Теперь я хотел бы получить список Serv на основе инфры.

Итак, я попробовал в LinkServInfraRepository:

    $qb = $this->createQueryBuilder('s')
            ->select('DISTINCT s.serv')
            ->where('s.infra = :infra')
            ->setParameter('infra', $infra);
    return $qb->getQuery()->getResult();

И получаю ошибку:

    [Semantical Error] near 'serv FROM': Error: InvalidPathExpression. 
     Must be a StateFieldPathExpression.

(Сначала я попробовал без DISTINCT и попробовал с ним, основываясь на ответе, найденном здесь).

Запрос кажется хорошим, потому что он:

    SELECT DISTINCT s.serv 
    FROM MyBundle\Entity\LinkServInfra s 
    WHERE s.infra = :infra

Как бы вы поступили? Спасибо!


person SMB Punt    schedule 10.01.2018    source источник


Ответы (2)


Поскольку отношение ТОЛЬКО в LinkServInfra, а не в Serv :

Я использовал отношение в LinkServInfra, чтобы сделать это...

    public function filter($type, $etat, $infra){

    $qb = $this->createQueryBuilder('l');
    $qb->where(' l.infra = :infra ')
       ->setParameter('infra', $infra);

    if( $type || $etat ){
       $qb->join('l.serv', 's')
       //where & setParameter for type
       //where & setParameter for detail
    }

И затем, когда я вызываю функцию filter :

    $entities = $em->getRepository('linkServInfra')->filter(//...
    $servs = array();
    foreach($entities as $entity){
        $servs[] = $entity->getServ();

    }

Я думаю, это не самое чистое решение, но оно работает...

person SMB Punt    schedule 18.01.2018

Я думаю, что вы не можете использовать DISTINCT для отношения, только для псевдонима корневого объекта.

Вы должны использовать сущность Serv как корневую и присоединиться к сущности LinkServInfra и infra через 2-й. Что-то типа:

$qb = $this->getDoctrine()
        ->getRepository(Serv::class)->createQueryBuilder('s')
        ->select('DISTINCT s')
        ->leftJoin("s.linkServInfra", "lsi")
        ->leftJoin("lsi.infra", "infra")
        ->where('infra.id = :infra')
        ->setParameter('infra', 1);

В качестве альтернативы, если отношение однонаправленное и вы не хотите делать его двунаправленным, вы можете использовать пользовательское соединение:

use Doctrine\ORM\Query\Expr\Join;

$qb = $this->getDoctrine()
        ->getRepository(Serv::class)->createQueryBuilder('s')
        ->select('DISTINCT s')
        ->leftJoin(LinkServInfra::class, "lsi", Join::WITH, 'lsi.serv = s')
        ->leftJoin("lsi.infra", "infra")
        ->where('infra.id = :infra')
        ->setParameter('infra', 1);

использованная литература

person Jannes Botis    schedule 12.01.2018
comment
Серв не знает отношения (мне нужно это сделать по некоторым причинам...), поэтому s.linkServInfra не существует, верно? - person SMB Punt; 18.01.2018
comment
Да, у вас однонаправленное отношение. Можно сделать двунаправленным. docs.doctrine-project.org/ проекты/doctrine-orm/en/latest/ - person Jannes Botis; 18.01.2018
comment
Да, но я не хочу, чтобы он был двунаправленным (как я уже сказал по некоторым причинам, но это другое обсуждение) - person SMB Punt; 19.01.2018