You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为无限层级的分类与子分类建立多对多模型关联?

Infinite Hierarchical Categories with Many-to-Many Relationships

Hey there! Let's walk through how to set up your model associations to handle infinite nested categories using your existing categories and subcategories tables.

First, let's recap your table logic:

  • categories: Stores all category core data (ID, title, description) — every parent/child category lives here.
  • subcategories: Acts as a pivot table to map parent-child relationships, using category_id (the child category's ID) and parent_category_id (the parent category's ID). This structure supports both many-to-many relationships (a category can have multiple parents/children) and infinite nesting.

Step 1: Model Associations (Laravel Eloquent Example)

We'll set up self-referential many-to-many relationships in the Category model, since we're linking categories to themselves via the pivot table.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Category extends Model
{
    protected $table = 'categories';

    // Get all parent categories this category belongs to
    public function parentCategories(): BelongsToMany
    {
        return $this->belongsToMany(
            self::class,
            'subcategories',       // Pivot table name
            'category_id',         // Foreign key for THIS category in the pivot table (child ID)
            'parent_category_id'   // Foreign key for the RELATED category in the pivot table (parent ID)
        );
    }

    // Get all child categories, recursively loading their children for infinite hierarchy
    public function childCategories(): BelongsToMany
    {
        return $this->belongsToMany(
            self::class,
            'subcategories',
            'parent_category_id',   // Foreign key for THIS category in the pivot table (parent ID)
            'category_id'           // Foreign key for the RELATED category in the pivot table (child ID)
        )->with('childCategories'); // Recursively load child categories' children
    }
}

Step 2: Using the Associations

Fetch a Category + All Nested Subcategories

To get a category and every level of its child categories:

// Get category ID 1 with all nested subcategories
$category = Category::with('childCategories')->find(1);

// Access top-level children
foreach ($category->childCategories as $child) {
    echo $child->title;

    // Access grandchildren, great-grandchildren, etc.
    foreach ($child->childCategories as $grandchild) {
        echo $grandchild->title;
        // This pattern continues infinitely for all nested levels
    }
}

Get a Tree-Structured Hierarchy

If you want a clean nested array/object for display (like in menus), add an accessor to the Category model:

// Add this to the Category model
public function getTreeChildCategoriesAttribute()
{
    return $this->childCategories->map(function ($child) {
        // Recursively attach children to each subcategory
        $child->setAttribute('children', $child->tree_child_categories);
        return $child;
    });
}

Then use it like this:

$category = Category::with('childCategories')->find(1);
$categoryTree = $category->tree_child_categories;

Key Notes

  • Performance Consideration: Recursive eager loading can cause N+1 query issues for very deep hierarchies. If you're dealing with a large number of categories, consider using the Nested Set pattern (there are dedicated packages that simplify this) which is optimized for hierarchical data.
  • Pivot Table Optimization: Your subcategories table doesn't strictly need an id column. You can set category_id and parent_category_id as a composite primary key to enforce unique parent-child pairs.
  • Other ORMs: The core idea translates to other frameworks — define a self-referential many-to-many relationship using the pivot table, then implement recursive loading for infinite nesting.

内容的提问来源于stack exchange,提问作者Andreas Hunter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:00:27