<p>Ok so here's how I ended up doing this. Essentially querying everything and adding a <code>sourceId</code> and <code>targetId</code> property to each result. In order to get this query to work though, we need to add a behavior to the Entry component to support two new properties, <code>sourceId</code> and <code>targetId</code>.</p>
<pre class="lang-php prettyprint-override"><code>// This basically left-joins the the relationship table to our sections. This allows us
// to essentially &quot;eager-load&quot; in reverse.
$relatedQuery = Entry::find()
  -&gt;section(['healthTopics', 'providers', 'locations'])
  -&gt;addSelect('relations.targetId')
   -&gt;addSelect('relations.sourceId')
   // You can query to get the field ids here, I just decided to look them up in the db.
    -&gt;leftJoin(
               '{{%relations}} relations' ,
                '([[elements.id]] = [[relations.sourceId]]) AND ([[relations.fieldId]] = 2 OR [[relations.fieldId]] = 5)'
            )
    -&gt;groupBy('elements.id')
    -&gt;all();

    // Same thing here, just looked up the section ids instead of querying for them.
    $healthTopics = ArrayHelper::where($relatedQuery, 'sectionId', '1');
    $providers = ArrayHelper::where($relatedQuery, 'sectionId', '3');
    $locations = ArrayHelper::where($relatedQuery, 'sectionId', '2');

</code></pre>
<p>Next, I needed to add a behavior to the Entry component so that it could support having the two new properties we added, <code>sourceId</code> and <code>targetId</code>.</p>
<pre class="lang-php prettyprint-override"><code>&lt;?php

namespace foo\behaviors;

use yii\base\Behavior;

class EntryBehavior extends Behavior
{
    public $targetId;
    public $sourceId;
}

</code></pre>
<pre class="lang-php prettyprint-override"><code>Event::on(Entry::class, Entry::EVENT_DEFINE_BEHAVIORS, static function (DefineBehaviorsEvent $event) {
    $event-&gt;behaviors['entryBehavior'] = ['class' =&gt; EntryBehavior::class];
});

</code></pre>

CC BY-SA 4.0
2021-02-17T21:19:40.767Z
2021-02-17T21:19:40.767Z
Myles Hyson
<p>So I have structures that are related in the follwing way:</p>

<ul>
<li><strong>Locations</strong> has many <strong>Providers</strong></li>
<li><strong>Providers</strong> has many <strong>Health Topics</strong></li>
</ul>

<p>I know that I can eager load all <strong>Locations</strong> with related <strong>Providers</strong> and <strong>Health Topics</strong> very easily using using something like this:</p>

<pre><code>craft.entries.section('locations').with(['providers.healthTopics']).all()
</code></pre>

<p>However how can I eager load the reverse relationship, loading all <strong>Health Topics</strong> with their related <strong>Providers</strong> and <strong>Locations</strong>? The eager loading function seems to go from parent to children but not from children to parent...though I could be missing something there? </p>

<entries><query><eager-loading><elementquery>
How do you eager load or join reverse relationships for entries?
# How do you eager load or join reverse relationships for entries?

(Asked by: username_0 on 2020-06-08)

So I have structures that are related in the follwing way:

Locations has many Providers
Providers has many Health Topics

I know that I can eager load all Locations with related Providers and Health Topics very easily using using something like this:
craft.entries.section('locations').with(['providers.healthTopics']).all()

However how can I eager load the reverse relationship, loading all Health Topics with their related Providers and Locations? The eager loading function seems to go from parent to children but not from children to parent...though I could be missing something there?

**Tags:** entries, query, eager-loading, elementquery


---

## 1 answers

### Answer by username_0 on 2021-02-17. Score: 3 | Accepted answer

Ok so here's how I ended up doing this. Essentially querying everything and adding a sourceId and targetId property to each result. In order to get this query to work though, we need to add a behavior to the Entry component to support two new properties, sourceId and targetId.
// This basically left-joins the the relationship table to our sections. This allows us
// to essentially "eager-load" in reverse.
$relatedQuery = Entry::find()
  ->section(['healthTopics', 'providers', 'locations'])
  ->addSelect('relations.targetId')
   ->addSelect('relations.sourceId')
   // You can query to get the field ids here, I just decided to look them up in the db.
    ->leftJoin(
               '{{%relations}} relations' ,
                '([[elements.id]] = [[relations.sourceId]]) AND ([[relations.fieldId]] = 2 OR [[relations.fieldId]] = 5)'
            )
    ->groupBy('elements.id')
    ->all();

    // Same thing here, just looked up the section ids instead of querying for them.
    $healthTopics = ArrayHelper::where($relatedQuery, 'sectionId', '1');
    $providers = ArrayHelper::where($relatedQuery, 'sectionId', '3');
    $locations = ArrayHelper::where($relatedQuery, 'sectionId', '2');


Next, I needed to add a behavior to the Entry component so that it could support having the two new properties we added, sourceId and targetId.

Event::on(Entry::class, Entry::EVENT_DEFINE_BEHAVIORS, static function (DefineBehaviorsEvent $event) {
    $event->behaviors['entryBehavior'] = ['class' => EntryBehavior::class];
});


---

