Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine DQL JOIN

I have the following entities mapped with Doctrine 2:

class Zone
{
    /**
     * @ManyToOne(targetEntity="Zone", inversedBy="children")
     * @var Zone
     */
    protected $parent;

    /**
     * @OneToMany(targetEntity="Zone", mappedBy="parent")
     * @var Zone[]
     */
    protected $children;

    /**
     * @ManyToMany(targetEntity="Zone")
     * @var Zone[]
     */
    protected $descendants;
}

class Restaurant
{
    /**
     * @ManyToOne(targetEntity="Zone")
     * @var Zone
     */
    protected $zone;
}

Basically, a Zone has a parent, and therefore children. Because children may have children themselves, each Zone keeps a list of all its descendants as well.

Each Restaurant is assigned a Zone.

What I want to do, is to perform a DQL JOIN to return all Restaurants in a specific Zone (including all of its descendants).

If I had to do this in plain SQL, I would write:

SELECT r.* from Zone z
JOIN ZoneDescendant d ON d.zoneId = z.id
JOIN Restaurant r ON r.zoneId = d.descendantId
WHERE z.id = ?;

Is it possible to do this with Doctrine DQL, without adding a $restaurants property on the Zone, and having to complexify the domain model uselessly?

like image 897
BenMorel Avatar asked Oct 28 '25 20:10

BenMorel


2 Answers

Ok, I finally found a way to do it with JOINs only (significantly faster on MySQL):

SELECT r
FROM Restaurant r,
     Zone z
JOIN z.descendants d
WHERE r.zone = d
AND z = ?1;
like image 55
BenMorel Avatar answered Oct 30 '25 12:10

BenMorel


The only way I can think of doing this in a single DQL query is to use a subquery:

SELECT r FROM Restaurant r WHERE r.zone IN (SELECT zc.id FROM r.zone z JOIN z.children zc WHERE z.id = :zoneId) OR r.zone = :zoneId
like image 38
Diego Avatar answered Oct 30 '25 11:10

Diego



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!