SasaT
SasaT

Reputation: 731

Laravel - define multi table relationships

I'm new to laravel and have to define relationships for 3 tables. The tables are events, categories, packages.

Event can have multiple categories and each category can have multiple packages. Same categories can be in various events.

So far i have following tables but not sure if i'm taking the right approach:

Table:events
id - int
title - varchar ...

Table: categories
id - int
name - varchar

Table:packages
id - int
name - varchar
price - decimal

Table:category_package
category_id - int
package_id - int

Table:event_package
event_id - int
package_id - int

Inside package model I have:

public function categories()
{
    return $this->belongsToMany('\App\Category');
}

public function events()
{
    return $this->belongsToMany('\App\Event');
}

Inside event and category model i have:

public function packages()
{
    return $this->belongsToMany('\App\Package');
}

I'd like to get the following result out when i query for specific event with its relationships:

[
   "events" => [
        "id" => 1,
        "title" => "whatever title",
        "categories" => [
            [
            "id" => 1,
            "name" => "the category",
            "packages" => [
                ["id" => 1, "name" => "pack1"],
                ["id" => 2, "name" => "pack2"],
                ["id" => 3, "name" => "pack3"]
            ]],
            [
            "id" => 2,
            "name" => "second cat",
            "packages" => [
                ["id" => 4, "name" => "pack4"],
                ["id" => 5, "name" => "pack5"],
                ["id" => 6, "name" => "pack6"]
            ]],
        ]
    ]
]

Is this possible in laravel and how would i go about it. I'm pretty sure I didn't take correct approach.

Thanks

Upvotes: 3

Views: 3769

Answers (1)

BrokenBinary
BrokenBinary

Reputation: 7899

Based on your table structure and your comments, it seems like you want this setup:

  • A Event has multiple Packages
  • A Package belongs to one Event
  • A Category has multiple Packages
  • A Package belongs to one Category

You don't need the pivot tables (category_package and event_package) so remove those. Then your packages table needs to have an event_id and category_id field added to it.

Table:packages
id - int
name - varchar
price - decimal
event_id - int
category_id - int

You should setup your models like this:

class Event extends Model {
    public function packages() {
        return $this->hasMany('App\Package');
    }
}

class Category extends Model {
    public function packages() {
        return $this->hasMany('App\Package');
    }
}

class Package extends Model {
    public function event() {
        return $this->belongsTo('App\Event');
    }

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

The array you are trying to get in your question can't be retrieved elegantly, you'll have to do some manual work, but it's not hard if you use eager loading with constraints.

To get one Event and its Categories and Packages you would do this:

$event = Event::find($eventId); // Or however you want to get the Event
$event['categories'] = Category::with(['packages' => function($query) use($event) {
    $query->where('event_id', $event->id);
}])->get();

To get multiple Events and their Categories and Packages you would just use a loop and add the categories for each Event.

$events = Event::all(); // Or however you want to get the Events
foreach ($events as $key => $event) {
    $events[$key]['categories'] = Category::with(['packages' => function($query) use ($event) {
        $query->where('event_id', $event->id);
    }])->get();
}

Upvotes: 1

Related Questions