skip to Main Content

I’m having trouble with the Laravel BelongsTo relation.

I want to loop through a collection of cooks and get meals from them.

I create the cooks collection like this:
$cooks = Cook::has('meals')->get();

Then I want to get the meals like this in a foreach loop:

foreach($cooks as $cook){
    $meals = $cook->meals()->get()
}

But the meals get stuck on the following function:

public function getCookNameAttribute()
    {
        return $this->cook->userProfile->firstname . ' ' . $this->cook->userProfile->lastname;
    }

I get the error that cook is null, but how is that possible if the query is run from the cook?

The relation looks like this:

public function cook(): BelongsTo
    {
        return $this->belongsTo(Cook::class);
    }

3

Answers


  1. Have you tried it with the foreign key and owner key?

    public function cook()
    {
        return $this->belongsTo(Cook::class, 'cook_id', 'id');
    }
    

    Eloquent One To One Relationship

    Login or Signup to reply.
  2. As it is right now when you do

      $meals = $cook->meals()->get();
    

    You’ll get a collection back containing only meals that belong to the cook, not also the cook, which is why the cook is null in your function.

    Either you need to add a ->with(‘cook’) to your first ->get() function but generally I wouldn’t recommend having a database query in a loop. Otherwise you could do

     return $this->cook()->get()->userProfile->firstname . ' ' . $this->cook()->get()->userProfile->lastname;
    

    but then you’ll perform a query every time you are looking for the first and the last name.

    Maybe get the cooks with their meals in one query in stead and then loop through the results:

    $cooks = Cook::with('meals')->get();
    echo($cooks);
    

    The look at the results you get back and loop through them to get the cook name and their respective meals?

    Login or Signup to reply.
  3. Use eager loading: Eager Loading

    $cooks = Cook::with("meals.cook.userProfile")
        ->has('meals')
        ->get();
    
    foreach($cooks as $cook){
        $meals = $cook->meals;
    }
    

    Then change your Model Accessor to:

    public function getCookNameAttribute()
    {
        return trim(
            ($this->cook?->userProfile?->firstname ?? '')
            . ' '
            . ($this->cook?->userProfile?->lastname ?? '')
        );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search