簡體   English   中英

Laravel 從父類別及其所有子類別中獲取所有產品

[英]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類別頁面中,我想顯示此表中的產品以及所有兒童產品。

所以它應該首先從ComputersAccessories以及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遞歸加載關系。

以下是讓您進行設置的步驟(在撰寫本文時)

  1. 運行composer require staudenmeir/laravel-adjacency-list:"^1.0"
  2. HasRecursiveRelationships特性添加到您的Category模型:

     use Staudenmeir\\LaravelAdjacencyList\\Eloquent\\HasRecursiveRelationships; class Category extends Model { use HasRecursiveRelationships; ... }
  3. 將您的查詢更改為:

     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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM