[英]Laravel get all products from parent category and all it's sub-categories
我正在嘗試從一個類別及其所有子類別中檢索產品。
這是我的categories
表:
| id | parent_id | name |
|---- |----------- |------------- |
| 1 | NULL | Electronics |
| 2 | 1 | Computers |
| 3 | 2 | Accessories |
| 4 | 3 | Keyboards |
這是我的產品表:
| id | category_id | name |
|---- |------------- |----------- |
| 1 | 2 | Product 1 |
| 2 | 3 | Product 2 |
| 3 | 4 | Product 3 |
假設我在Computers
類別頁面中,我想顯示此表中的產品以及所有兒童產品。
所以它應該首先從Computers
和Accessories
以及Keyboards
獲取產品。
這是我的類別模型:
public function parent() {
return $this->belongsTo(Category::class, 'parent_id');
}
public function childs() {
return $this->hasMany(Category::class, 'parent_id');
}
public function products() {
return $this->hasManyThrough(Product::class, Category::class, 'parent_id', 'category_id', 'id');
}
產品型號 :
public function categories() {
return $this->belongsTo(Category::class, 'category_id');
}
查詢:
Category::with(['products', 'childs.products'])->where('id', $category->id)->get();
返回:
{
"id":11,
"parent_id":4,
"name":"Computers",
"products":[
{
"id":2,
"category_id":12,
"title":"Product 1",
"laravel_through_key":11
}
],
"childs":[
{
"id":12,
"parent_id":11,
"name":"Accessories",
"products":[
{
"id":1,
"category_id":13,
"user_id":1,
"title":"Product 2",
"laravel_through_key":12
}
]
}
]
}
上面,它正在轉義最后一個子類別Keyboards
。
我曾嘗試使用hasManyThrough
關系,但我只從Computers
and Accessories
獲得產品,但沒有接觸到Keyboards
。
所以如果我在一個類別中,我想從這個類別樹中獲取所有產品。 即使一個子類別有子類別。
我怎樣才能做到這一點?
謝謝。
更新:
我在Foued MOUSSI的回答中應用了片段:
public function childrenRecursive() {
return $this->childs()->with('childrenRecursive');
}
$categoryIds = Category::with('childrenRecursive')->where('id', $category->id)->get();
返回:
[
{
"id":2,
"parent_id":1,
"name":"Computers",
"children_recursive":[
{
"id":3,
"parent_id":2,
"name":"Accessories",
"children_recursive":[
{
"id":4,
"parent_id":3,
"name":"Keyboards",
"children_recursive":[]
}
]
}
]
}
]
我得到了類別數組及其所有子類別,但是要從所有這些類別中獲取產品,我需要使用childrenRecursive
從列表中提取 ID 來調用類似的東西:
Product::whereIn('category_id', $categoryIds)->get();
任何的想法?
您可以通過以下方式修復它:
建立遞歸關系:(請在此處參考 Alex Harris 的回答)
// recursive, loads all descendants
// App\Category
public function childrenRecursive()
{
return $this->childs()->with('childrenRecursive');
}
$data = Category::with(['products', 'childrenRecursive', 'childrenRecursive.products'])->where('id', 2)->get()->toArray();
#Edit:提取產品列表
在控制器中定義Flatten laravel 遞歸關系集合(樹集合)函數
public function flatten($array)
{
$flatArray = [];
if (!is_array($array)) {
$array = (array)$array;
}
foreach($array as $key => $value) {
if (is_array($value) || is_object($value)) {
$flatArray = array_merge($flatArray, $this->flatten($value));
} else {
$flatArray[0][$key] = $value;
}
}
return $flatArray;
}
然后為了只有產品項目
$data = Category::with(['products', 'childrenRecursive', 'childrenRecursive.products'])->where('id', 2)->get()->toArray();
$flatten = $this->flatten($data);
foreach ($flatten as $key => $fl) {
// eliminate categories from $flatten array
if (!array_key_exists('category_id', $fl)) {
unset($flatten[$key]);
}
}
$product = array_values($flatten);
一種選擇是使用類似laravel-adjacency-list 的東西。 這將允許您使用CTE遞歸加載關系。
以下是讓您進行設置的步驟(在撰寫本文時)
composer require staudenmeir/laravel-adjacency-list:"^1.0"
將HasRecursiveRelationships
特性添加到您的Category
模型:
use Staudenmeir\\LaravelAdjacencyList\\Eloquent\\HasRecursiveRelationships; class Category extends Model { use HasRecursiveRelationships; ... }
將您的查詢更改為:
Category::with('descendants.products')->where('id', $id)->first(); //$id being the id of the parent category you want to get.
如果您只想獲取屬於/屬於某個類別的產品,您可以執行以下操作:
Product::whereHas('category', function ($query) use ($category) {
$query->whereIn('categories.id', $category->descendantsAndSelf()->select('id')->getQuery());
})->get();
有關如何使用laravel-adjacency-list
更多信息,請參閱文檔。
$categories = Category::whereParentId(null)->with('children.children.children')->get();
並且在視圖中您可以使用 foreach 循環顯示項目
由於我使用的是 MySQL 5,如果有人對此感興趣,我會使用這種方式來解決我的項目中的這個問題。 這對我來說更有意義。
如果您使用的是 MySQL 8,則可以將此問題作為參考來編輯此代碼。 如何創建 MySQL 分層遞歸查詢?
public function scopeWhereCategoryId($query, $category_id){
return $query->where(function($query) use ($category_id){
$query->where('category_id', trim($category_id));
$query->orWhereRaw("category_id in (
select id
from (select * from pm_categories
order by category_id, id) categories_sorted,
(select @pv := '" . trim($category_id) . "') initialisation
where find_in_set(category_id, @pv)
and length(@pv := concat(@pv, ',', id))
)");
});
}
如果你使用 ORM Eloquent 關系
public function categoriesProduct(ProductCategory $category)
{
$categories = ProductCategory::where('parent_id', $category->id)
->orWhere('id', $category->id)
->latest()
->get();
return view('categoryProduct', compact('categories', 'category'));
}
我認為更好的方法是文章Eloquent: Recursive hasMany Relationship with Unlimited Subcategories
只需將產品關系添加到類別模型
Class Category extends Model
public function categories()
{
return $this->hasMany(Category::class, 'parent_id');
}
public function childrenCategory()
{
return $this->hasMany(Category::class, 'parent_id')->with('categories');
}
public function products()
{
return $this->hasMany(Product::class);
}
詢問:
$Categories = Category::whereNull('parent_id')
->with('childrenCategory','products')
->get();
返回:
[
{
"id": 1,
"parent_id": null,
"name": "Category 1",
"description": "Category 1",
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z",
"products": [
{
"id": 1,
"category_id": 1,
"name": "productNobis provident.",
"description": "Ad quia ullam voluptatem modi ab dolorem non.",
"qty": 1,
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z"
},
],
"children_categories": [
]
},
{
"id": 2,
"parent_id": null,
"name": "Category 2",
"description": "Laborum aut quibusdam earum commodi.",
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z",
"products": [
{
"id": 5,
"category_id": 2,
"name": "productVoluptas laborum adipisci.",
"description": "Autem ut et voluptate ab sit voluptatem quia.",
"qty": 1,
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z"
},
],
"children_categories": [
{
"id": 4,
"parent_id": 2,
"name": "Category 4",
"description": "Eos nemo libero non eius voluptates.",
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z",
"products": [
{
"id": 9,
"category_id": 4,
"name": "productSunt deleniti minus.",
"description": "Vitae numquam autem consequuntur consequuntur.",
"qty": 1,
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z"
},
],
"categories": [
{
"id": 6,
"parent_id": 4,
"name": "Rerum qui earum.",
"description": "Nihil ipsum officiis vitae et error accusamus ipsam.",
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z",
"products": [
{
"id": 13,
"category_id": 6,
"name": "productConsequatur quisquam molestiae.",
"description": "Autem sed mollitia eos eveniet iste ipsa aut aliquam.",
"qty": 1,
"created_at": "2021-12-10T11:43:48.000000Z",
"updated_at": "2021-12-10T11:43:48.000000Z"
},
]
}
]
}
]
}
]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.