Home > Mobile >  How to disable loading of relationships when not needed in Laravel
How to disable loading of relationships when not needed in Laravel

Time:03-20

is it possible to disable the loading of relationships, but only in some cases?

Here are my models:

class League extends Model
{
    ...

    public function country()
    {
        return $this->belongsTo(Country::class)->with('translations');
    }
}

class Country extends Model
{
    ...

    public function translations()
    {
        return $this->hasMany(CountryTranslation::class, 'country_id');
    }
}

class CountryTranslation extends Model
{
    ...
}

In many places, I need to load the translations relationship for Country, but on some pages, I want to display information about the League and its Country only. There I don't want to show the CountryTranslation collection.

Here is the code for that page:

$country = $league->country;

Is it possible only for this line to disable the relations?

CodePudding user response:

he with() simply eager loads the translations to avoid additional queries, but you should be able to load the translations with and without it, without with( adds additional queries. https://laravel.com/docs/9.x/eloquent-relationships#eager-loading

You will want to change:

    public function country()
    {
        return $this->belongsTo(Country::class)->with('translations');
    }

to

    public function country()
    {
        return $this->belongsTo(Country::class);
    }

If you want to load translations, you can do it in the controllers

// if you want translations at some point do this:
$league = League::with('country.translations')
$country = $league->country->translations

// if you do not want translations
$league = League::with('country')
$country = $league->country;

If you do not want to touch:

    public function country()
    {
        return $this->belongsTo(Country::class)->with('translations');
    }

you can create another method

    public function countryClean()
    {
        return $this->belongsTo(Country::class);
    }

$country = $league->countryClean;

CodePudding user response:

So, you're currently finding out one of the reasons for not defining the eager loading inside of the relationship. The first suggestion would be to remove the with() from the relationship definition, and add it in where needed. If desired, you can create another relationship that has the eager loading enabled, and it can use the base relationship to keep it DRY:

public function country()
{
    return $this->belongsTo(Country::class);
}

public function countryWithTranslations()
{
    return $this->country()->with('translations');
}

If this code change is not feasible, you will need to change how you're accessing the country relationship. When you access the relationship attribute, it lazy loads the relationship, and you don't have the ability to modify the relationship query. So, instead of accessing the relationship attribute, you'd need to call the relationship query so you can modify it.

Therefore, you won't be able to do $country = $league->country;, but you can do:

$country = $league->country()->without('translations')->first();
  • Related