We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Eager loading models - Differences between ->getRelated('model') and ->model (db accesses)

Hello!

Using Phalcon's ORM, I found a strange thing.

I have 3 models with the appropriate relations defined between them - say m1 has one m2 (alias rel12), m2 has one m3 (alias rel23).

I am accessing the database using QueryBuilder, and I fetch the 3 models / row. I then iterate over the resultset and manually set the relations between the models received and store the "main" model in an array. This is an attempt to eager load the models I know I want in the future. Example:


$builder = $this->getModelsManager()->createBuilder();
$results = $builder
    ->columns("m1.*,m2.*,m3.*")
    ->addFrom("Models\M1","m1")
    ->join(
        "Models\M2",
        "m1.m2_id = m2.m2_id",
        "m2"
    )
    ->join(
        "Models\M3",
        "m2.m3_id = m3.m3_id",
        "m3"
    )
    ->getQuery()
    ->execute();

$arr = array();

foreach($results as $res) {
    $res->m2->rel23 = $res->m3;
    $res->m1->rel12 = $res->m2;
    $arr[] = $res->m1;
}

This way, I get an array with the main models I wanted (m1 models), and I can successfuly access its relation (r12), BUT NOT if I use the getRelated method.

Example:


echo $arr[0]->r12->m2_id; 
// Does not cause a database access to fetch the related model2.
echo $arr[0]->getRelated('r12')->m2_id
// Does cause a database access, fetching the already loaded model2.

So, I am not sure if this is just "how things are" or if this is an awkard consequence of my awkard manual setting of the related models. If the second case is true, is it a better way of doing this?

Thank you so much

Ok, so I implemented a getter method in each model - getM2() in model M1, for example, and it works ok (no unexpected db accesses).

I feel a bit dumb because I didn't check the source code of phalcon before I posted this topic (and after I found this). Indeed, getRelated method is fetching the related model from the database using find or findFirst. I really thought that it would use the loaded model if it existed in memory. And so when I accessed ->rel12 it was internally using getRelated('rel12') - magic.

But I guess that it was not the point of the method. My bad. Wouldn't it be a cool feature, though?

Even so, if anybody would correct me if I am doing something that could be improved, it would be much appreciated.

getRelated does not store the result in the 'parent' model, it only fetches from database, so each time is called a query is made (I think unless you use the reusable key in the relation).

If you want eager-loading I've written a package a few days ago, check it