vendredi 27 mai 2016

Laravel 5: Lazy Eager Loading without repeating queries

In my project I'm writing a method on one of my models that uses one of it's relationships and a sub-relationship so I am having to use lazy eager loading:

class MyModel extends Model
{
    public function doSomething()
    {
        // Lazy eager load relationship and subrelationship
        $this->load('relationship', 'relationship.subrelationship');

        $relatedItems = $this->relationship;
        foreach ($relatedItems as $relatedItem) {
            $subrelatedItems = $relatedItem->subrelationship;
            foreach ($subrelatedItems as $subrelatedItem) {
                // Do something...
                return true;
            }
        }

        return false;
    }
}

The Model::load() method in Laravel can be used to re-load a relationship and does a new database query every time. Therefore, each time I call my method MyModel::doSomething(), (Or call another method that uses similar relationships) another database query is executed.

I know that in Laravel you can call a relationship a number of times like this:

$relatedItems = $model->relationship;
$relatedItems = $model->relationship;
$relatedItems = $model->relationship;
$relatedItems = $model->relationship;

..and it doesn't repeat the query since it has already loaded the relationship.

I was wondering if it was possible to avoid querying the database every time I want to use my relationship inside the model? I had the idea that I could use $this->getRelations() to work out which relationships had been loaded and then just skip them if they already had:

$toLoad = ['relationship', 'relationship.subrelationship'];
$relations = $this->getRelations();
foreach ($toLoad as $relationship) {
    if (array_key_exists($relationship)) {
        unset($toLoad[$relationship]);
    }
}

if (count($toLoad) > 0) {
    $this->load($toLoad);
}

That works to an extent, it's able to skip loading relationship each time, but relationship.subrelationship isn't actually stored in the array returned by $this->getRelations(). I would imagine it is stored in the sub-model(s) as subrelationship.

Cheers



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire