Eudoxus
Eudoxus

Reputation: 283

Laravel relationship between three tables

I have 3 tables:

Which I was relating them in the following way:

Basically, a book can have many ages, an age can have many books, an event can have many ages, an event age can have many books.

My Event Model looks like this and works fine to get all event ages

class Event extends Model
{
    public function ages()
    {
        return $this->belongsToMany(Age::class, 'event_age');
    }
}

Age Model:

class Age extends Model
{
    public function books(): BelongsToMany
    {
        return $this
            ->belongsToMany(Book::class)
            ->withTimestamps();
    }
}

Book Model

class Book extends Model
{
    public function ages(): BelongsToMany
    {
         return $this
            ->belongsToMany(Age::class, 'book_age', 'book_id','age_id')
            ->withTimestamps();
    }
}

Im having trouble figuring out how to get all edition age books, is it possible to do it on the Event model?

Upvotes: 0

Views: 67

Answers (1)

J. A. Streich
J. A. Streich

Reputation: 1702

Let's Review The Relationships

Seems you should only need 3 models, and 5 tables.

  • Books Belong to Ages
  • Events Belong to Ages
  • Ages Belongs to Books
  • Ages Belongs to Events

Your other models are alright, but your age model is missing a relationship to Event:

class Age extends Model
{
    public function books(): BelongsToMany
    {
        return $this->belongsToMany(Book::class)
            ->withTimestamps();
    }

    public function events(): BelongsToMany
    {
        return $this->belongsToMany(Events::class,'event_age')
            ->withTimestamps();
    }
}

That would allow:

$books->ages;
$events->ages;
$ages->book;
$ages->events;

And chaining...

$books = collect();
foreach($event->ages as $age){
    $books->merge($ages->books);
}
$books->unique();

Books and Events

So, I gon't think you want age_event_books. I think what you really want is:

  • Events belong to Books
  • Books belong to Events

such that

book_events
- id
- book_id
- event_id
- age_id

And you'd have in book:

public function events()
{
    return $this->BelongsToMany('App\Event')
       ->withTimestamps()
       ->withPivot('age_id');
}

And in event:

public function books()
{
   return $this->belongsToMany('App\Book')->withTimestamps()
      ->withPiviot('age_id')->groupBy('age_id');
}

Giving you:

$event->books
$book->events

On the Front End

[O]n the frontend i'll need to get the most recent event and group books by age and books can belong to more than one age

$event = Event::latest();
$books = $event->books();

Then on the blade

@foreach($books as $age_id => $books)
    <h4>{{Age::find($age_id)->name}}</h4>
    @foreach($books as $book)
       <div>$book->name</div>
    @endforeach
@endforeach

Helpful Tip

You are supplying the relation table, which you have to do because you didn't follow the naming convention for joining tables. The convention is that the classes being joined should be listed alphabetically. So age_event instead of event_age.

Upvotes: 1

Related Questions