简体   繁体   中英

Laravel Eloquent - Get nested relationships with filtered data

suppose I have the following models:

Categories-(hasMany/belongsTo)-Subcategories-(hasMany/belongsTo)-Products

These models create a collapsible product list in the frontend, like so:

Category1
  - Subcategory1
    - Product1
    - Product2
Category2
  - SubCategory3
    - Product4

Now, I want to search for Product1 and retrieve it while keeping the relationship Category->Subcategory->Product intact, so that I can easily print it out like so:

Category1
 - Subcategory1
  - Product1

I know that with the following query you can search all categories that have a product with a certain condition:

<?php
    $Categories = Categories::whereHas('subcategories', function ($q) use ($request) {
        $q->whereHas('products', function ($q) use ($request) {
            $q->where('name', 'LIKE', "%$request->search%")
              ->orWhere('article_number', 'LIKE', "%$request->search%");
        });
    })
    ->get();
?>

But that only returns the categories.

I was then going to turn them into a collection with the following resource class, before I learned I actually only get the categories from the query above:

$Collection = CategoriesResource::collection($Categories);

//------------------------------------------------

class CategoriesResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'subcategories' => $this->subcategories()->with('products')->get(),
        ];
    }
}

My question is, can I either use a different query beforehand, or pass a condition to the with-statement, so that I will only get products that meet the search condition? Ideally, I'd want to have no empty categories or subcategories in the dataset, but if it's not manageable otherwise, it'd be ok.

I also tried it in the reverse by searching through products directly and get the categories with the belongsTo relationship, but I don't know a feasible way to reverse Product->Categories back to Categories->Products.

you can repeat the same condition on eager loading:

  $Categories = Categories::whereHas('subcategories', function ($q) use ($request) {
        $q->whereHas('products', function ($q) use ($request) {
            $q->where('name', 'LIKE', "%$request->search%")
                ->orWhere('article_number', 'LIKE', "%$request->search%");
        });
    })->with(['subcategories'=> function ($q) use ($request) {
        $q->with(['products'=>function ($q) use ($request) {
            $q->where('name', 'LIKE', "%$request->search%")
                ->orWhere('article_number', 'LIKE', "%$request->search%");
        }]);
    }])->get();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM