mafortis
mafortis

Reputation: 7138

How to get nested data in laravel

Logic

  1. Category has Products
  2. Products has brand(1), options(0 or many), tags(0 or many), rating(0 or many)
  3. I want get every brand, options, tags, ratings under current category in arrays

Note: returned data are category based not database based, so each category return different set of data based on what has been provided to that category products.

Code

Controller

public function show($slug)
{
    $category = Category::where('active', 'yes')->where('slug', $slug)->with('products')->first();
    return response()->json([
        'data' => new CategoriesFrontResource($category),
        'success'=>'Category retrieved successfully'
    ], 200);
}

Category model

public function products(){
  return $this->belongsToMany(Product::class, 'category_products', 'category_id', 'product_id');
}

Product model

public function categories(){
  return $this->belongsToMany(Category::class, 'category_products', 'product_id', 'category_id');
}

public function options(){
  return $this->belongsToMany(Option::class, 'option_products', 'product_id', 'option_id');
}

public function tags(){
  return $this->belongsToMany(Tag::class, 'product_tags', 'product_id', 'tag_id');
}

public function brand(){
  return $this->belongsTo(Brand::class);
}

public function rating(){
  return $this->morphMany(Rating::class, 'rateable');
}

Any idea how to achieve that goal?

Update

Based on Jeemusu answer here is what I have currently

$category = Category::where('active', 'yes')->where('slug', $slug)->with(['products', 'products.options', 'products.variations', 'products.brand', 'products.tags', 'products.rating'])->first();
$products = $category->products;
$tags = $products->tags->toArray();

And this is the results

Property [tags] does not exist on this collection instance.

Upvotes: 3

Views: 158

Answers (2)

mafortis
mafortis

Reputation: 7138

Solved

Following code fixed my issue of getting arrays of each data, but it still needs small fix to return unique data which I created new question for that.

    $data = [];
    foreach($products as $i => $product) {
        $data[$i]['brand'] = $product->brand;
        $data[$i]['rating'] = $product->rating;
        $data[$i]['variations'] = $product->variations;
        $data[$i]['options'] = $product->options;
        $data[$i]['tags'] = $product->tags;
    }

Upvotes: 1

Jeemusu
Jeemusu

Reputation: 10533

In the same way you used eager loading to retrieve products related to the category, you can also use nested eager loading to load those products relations.

To quote the documentation:

To eager load nested relationships, you may use "dot" syntax. For example, let's eager load all of the book's authors and all of the author's personal contacts in one Eloquent statement:

For your particular query you can do the following:

$category = Category::where('active', 'yes')
    ->where('slug', $slug)
    ->with(
        'products.brand', 
        'products.options', 
        'products.tags', 
        'products.ratings'
    )->first();

You can then access the data as you would any object returned from a query:

@foreach($category->products as $product
    <h1>{{ $product->brand->title }}</h1>
    @foreach($product->tags as $tag)
        <span>{{ $tag->title }}</span>
    @endforeach
@endforeach

Upvotes: 0

Related Questions