DQL за този SQL израз в Doctrine2 с връзка ManyToMany

Направих тази SQL заявка, за да получа данните, от които се нуждая от DB, и тя работи точно както искам:

SELECT DISTINCT ofreg.nombre as oficina 
  FROM nomencladores.oficina_regional AS ofreg  
  LEFT JOIN negocio.solicitud_usuario_oficina_regional AS solusofreg
    ON (ofreg.id = solusofreg.oficina_regional_id)
  JOIN nomencladores.tipo_tramite tram
    ON (tram.id = solusofreg.tipo_tramite_id)
  WHERE (tram.id = 1);

Тъй като връзката ми няма да генерира никакво допълнително поле в третата таблица, тогава решавам да отида за правилни анотации на моите обекти, погледнете:

class TipoTramite
{
    use IdentifierAutogeneratedEntityTrait;
    use NamedEntityTrait;
    use ActiveEntityTrait;

    /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\OficinaRegional", inversedBy="tipoTramites", cascade={"persist"})
     * @ORM\JoinTable(name="negocio.solicitud_usuario_oficina_regional", schema="negocio",
     *      joinColumns={@ORM\JoinColumn(name="oficina_regional_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")}
     * )
     */
    protected $oficinaRegionals;
}

class OficinaRegional
{
    use IdentifierAutogeneratedEntityTrait;
    use NamedEntityTrait;
    use ActiveEntityTrait;

    /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\TipoTramite", mappedBy="oficinaRegionals", cascade={"persist"})
     */
    protected $tipoTramites;
}

Имайки тези обекти и предполагайки, че са прави (поправете ме, ако греша), трябва да напиша DQL, който да отговаря на горния SQL код, може ли някой да ми помогне с написването на този DQL?

Винаги съм го правил с посредник, но този случай е напълно нов за мен. Освен това знам заобиколно решение за това и ще създам view на ниво DB и ще напиша обект само за този изглед без метод set само методите get, тъй като ще бъде обект само за четене, но не знам дали е прав път и наистина ми харесва да се науча как да го правя с помощта на ManyToMany (в моя проект имам много връзки от този тип, така че със сигурност ще имам нужда от тази помощ по-късно в близко бъдеще).

АКТУАЛИЗАЦИЯ

Добре, бих искал да продължа да следя този проблем и направих някои тестове, но без никакви полезни резултати, ето моите опити:

Първи подход

public function filtrarOficinaRegionalPorTramite($tramite)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
        ->select('ofr.nombre AS oficinaRegional, ttr.nombre as tipoTramite')
        ->from("AppBundle:OficinaRegional", "ofr")
        ->where("ofr.activo = :activo")
        ->leftJoin("AppBundle:TipoTramite", "ttr");

    $qb->setParameter('activo', TRUE);

    if ($tramite != NULL) {
        $qb->andWhere('ttr.id = :tramite');
        $qb->setParameter('tramite', $tramite);
    }

    echo $qb->getQuery()->getSQL();
    return $qb->getQuery()->getResult();
}

Не работи, тъй като резултатът SQL от предишния код е този:

SELECT n0_.nombre AS nombre0, n1_.nombre AS nombre1 
FROM nomencladores.oficina_regional n0_ 
LEFT JOIN nomencladores.tipo_tramite n1_ 
 ON (n0_.activo = ?) 

Втори подход

public function filtrarOficinaRegionalPorTramite($tramite)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
        ->select('ofr.nombre AS oficinaRegional, ttr.nombre as tipoTramite')
        ->from("OficinaRegional ofr")
        ->where("ofr.activo = :activo")
        ->leftJoin('ofr.TipoTramite ttr');

    $qb->setParameter('tramite', $tramite);

    if ($tramite != NULL) {
        $qb->where('ttr.id = :tramite');
        $qb->setParameter('tramite', $tramite);
    }

    return $qb->getQuery()->getResult();
}

Но получих тази грешка:

Предупреждение: Липсва аргумент 2 за Doctrine\ORM\QueryBuilder::from(), извикан в /var/www/html/project.dev/src/AppBundle/Entity/Repository/RegionalOfficeRepository.php на ред 25 и дефиниран в /var/ www/html/project.dev/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php ред 721

Трети подход

След като мина огромно количество време в опити да накарам нещата да работят, все още имам проблеми, но този път съм по-близо до отстраняването им. И така, ето последния ми изстрел с този код:

public function filtrarOficinaRegionalPorTramite($tramite)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
        ->select('ofr.nombre AS oficinaRegional, ttr.nombre as tipoTramite')
        ->distinct()
        ->from("AppBundle:OficinaRegional", "ofr")
        ->where("ofr.activo = :activo")
        ->leftJoin("ofr.tipoTramites", "ttr");

    $qb->setParameter("tramite", $tramite);

    if ($tramite != NULL) {
        $qb->andWhere("ttr.id = :tramite");
        $qb->setParameter("tramite", $tramite);
    }

    echo $qb->getQuery()->getSQL();
    return $qb->getQuery()->getResult();
}

Получих този SQL:

SELECT DISTINCT n0_.nombre AS nombre0,
                n1_.nombre AS nombre1
FROM nomencladores.oficina_regional n0_
  LEFT JOIN negocio.solicitud_usuario_oficina_regional n2_ ON n0_.id = n2_.tipo_tramite_id
  LEFT JOIN nomencladores.tipo_tramite n1_ ON n1_.id = n2_.oficina_regional_id
WHERE n0_.activo = ?
      AND n1_.id = ?;

Което изобщо не е грешно, но ето как трябва да бъде крайният SQL:

SELECT DISTINCT n0_.nombre AS nombre0,
                n1_.nombre AS nombre1
FROM nomencladores.oficina_regional n0_
  LEFT JOIN negocio.solicitud_usuario_oficina_regional n2_ ON n0_.id = n2_.oficina_regional_id
  LEFT JOIN nomencladores.tipo_tramite n1_ ON n1_.id = n2_.tipo_tramite_id
WHERE n0_.activo = TRUE
      AND n1_.id = 1;

Какво правя грешно?


person ReynierPM    schedule 04.11.2014    source източник


Отговори (1)


Изглежда, че съпоставянията на вашите колони за присъединяване са неправилни за TipoTramite, опитайте да ги обърнете.

 /**
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\OficinaRegional", inversedBy="tipoTramites", cascade={"persist"})
 * @ORM\JoinTable(name="negocio.solicitud_usuario_oficina_regional", schema="negocio",
 *      joinColumns={@ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="oficina_regional_id", referencedColumnName="id")}
 * )
 */

http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#one-to-many-unidirectional-with-join-table

Що се отнася до въпросителните знаци, това са само параметри, които ще бъдат попълнени по-късно.

person Justin    schedule 04.11.2014
comment
Да, това е проблемът и бях открит преди няколко минути и щях да отговоря на собствения си въпрос, но тъй като го направихте, наградата отива при вас, благодаря за съвета - person ReynierPM; 04.11.2014