laravelloadinglaravel-5.6eager

Laravel 5.6 eager load nested childrelations


I'm having an issue with getting child relations from a Card object to a User object. The relations are as following:

'User' -> hasOne 'Company' 
'Company' -> hasMany 'Card'

So the other way around is:

'Card' -> belongsTo 'Company' 
'Company' -> belongsTo 'User'

My Card model has got this:

public function company()
{
    return $this->belongsTo('App\Company');
}

My Company model has got this:

public function user()
{
    return $this->belongsTo('App\User');
}

public function cards()
{
    return $this->hasMany('App\Card');
}

My User model has got this:

public function company()
{
    return $this->hasOne('App\Company');
}

What I want to do is: in the User model I want to eager load all cards from that user. So my code looks like this:

$cards = Card::with('company.user')->get();

But it's constantly returning me all the card records in the database, not the ones that are from the logged in user itself. There definitely is a userID, cause when I dump $this->id in the User model, I'm getting the ID '1'. In the database I've configured all foreign keys so that won't be the problem I assume.

Table 'cards' has a foreign key to 'company_id', and table 'companies' has a foreign key to 'user_id', they are all set by the migration script, which looks like this:

Schema::create('cards', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('amount');
        $table->string('status');
        $table->unsignedInteger('company_id');
        $table->timestamp('expires_at')->nullable();
        $table->boolean('is_debit_allowed')->default(1);
        $table->string('cancelled_by')->nullable();
        $table->timestamp('cancelled_at')->nullable();
        $table->timestamps();
        $table->foreign('company_id')->references('id')->on('companies');
    });

What am I doing wrong guys?


Solution

  • In the User model, you can add it to the $with array:

    // this will eager load the company and cards for every user query, so beware!
    protected $with = ['company.cards'];
    

    Or create a new function cards:

    public function cards()
    {
        return $this->company->cards;
    }
    
    $cards = $user->cards();
    
    // use the auth helper to get logged in user's cards
    $cards = auth()->user()->cards();
    

    This should work for accessing via Card:

    $cards = Card::whereHas('company.user', function ($query) {
        $query->whereKey(auth()->id());
    })->get();