James
James

Reputation: 16339

Accessing relationship of a relationship

I am adding in an announcements feature to my application.

I have an announcements table which stores the announcement and an announcement_active table which stores the undismissed announcements for each user.

When an announcement is created, a record is generated in the announcements table to store this and a record entered in to the announcement_active table for every user for that announcement.

My user model holds a relationship for the active announcements:

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

I am then accessing this in my view to check for any undismissed announcements like this:

@if (Auth::user()->activeAnnouncements()->count() > 0)
    //code
@endif

The above works fine, it is when I am trying to do a for each loop on the announcements that I am having trouble:

@if (Auth::user()->activeAnnouncements()->count() > 0)
    @foreach(Auth::user()->activeAnnouncements()->announcement as $announcement)
      //code to display announcement
   @endforeach
@endif

It is when I am chaining ->announcement that I run in to trouble. I have defined the relationship like so:

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

However I get the error:

Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$announcement

When using Tinker and running \App\User::find(1)->activeAnnouncements()->first()->announcement the correct announcement shows.

Where am I going wrong when trying to load these in to my foreach loop?

Upvotes: 0

Views: 56

Answers (2)

Bastien Philippe
Bastien Philippe

Reputation: 116

In your class User, definine a announcements relation like this :

public function announcements() {
    return $this->hasManyThrough(Announcement::class,ActiveAnnouncement::class);
}

You can then access user's announcement with announcement :

@if (Auth::user()->announcements()->count() > 0)
    @foreach(Auth::user()->announcements as $announcement)
      //code to display announcement
   @endforeach
@endif

Nota : Maybe you could simply add a column is_active in announcement and drop ActiveAnnouncement model. This way, define announcements relation in your class User :

In your class User, definine a announcements relation like this :

public function announcements() {
    return $this->hasMany(Announcement::class);
}

and access active announcements via :

$activeAnnouncements = $user->announcements()->whereIsActive(true)->get()

Hope this will help

Upvotes: 0

Joel Hinz
Joel Hinz

Reputation: 25384

You're never actually retrieving the data in your foreach. Instead, Laravel thinks you're saying "build this query, don't execute it, then look for a property called 'announcement' on it". If you just change it to a get() call, it should work:

@foreach(Auth::user()->activeAnnouncements()->get() as $announcement)

Or better yet, use the automatic property version:

@foreach(Auth::user()->activeAnnouncements as $announcement)

By the way, it looks like you might want to check out Blade's @each functionality: https://laravel.com/docs/5.3/blade#rendering-views-for-collections

Upvotes: 1

Related Questions