Laravel 11.x无限级分类推荐使用自引用关系,核心字段包括id、name、slug、parent_id(nullable)、order_column、is_active及时间戳,并在迁移中添加parent_id外键约束指向自身表。

在 Laravel 11.x 中实现无限级分类(如菜单、商品类目、文章栏目等),推荐使用「自引用关系」+「迁移文件定义基础字段」的方式。迁移文件本身不处理层级逻辑,而是为模型关联和后续递归查询打下结构基础。
核心字段设计(必须包含)
一个典型的无限级分类表(例如 categories)至少需要以下字段:
- id:主键(默认已有)
- name:分类名称(string)
- slug:可选,用于 URL 友好标识(string, unique)
-
parent_id:外键,指向本表的
id,表示父级分类(unsignedBigInteger,允许 null) - order_column:可选,用于手动排序(integer,默认 0)
- is_active:可选,启用/禁用状态(boolean,默认 true)
- created_at / updated_at:时间戳(默认有)
Laravel 11.x 迁移文件示例
运行命令生成迁移:
php artisan make:migration create_categories_table
编辑生成的文件,内容如下:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(Blueprint $table): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique()->nullable();
$table->unsignedBigInteger('parent_id')->nullable();
$table->integer('order_column')->default(0);
$table->boolean('is_active')->default(true);
$table->timestamps();
// 添加外键约束(Laravel 11 默认使用 InnoDB,支持外键)
$table->foreign('parent_id')
->references('id')
->on('categories')
->onDelete('cascade'); // 子分类随父级删除而删除(按需调整)
});
}
public function down(Blueprint $table): void
{
Schema::dropIfExists('categories');
}
};
注意事项与补充说明
- 外键约束在 MySQL 中需确保存储引擎为
InnoDB(Laravel 默认满足);SQLite 不支持外键级联,开发时注意切换数据库驱动测试 -
parent_id设为nullable()是关键,根节点即为parent_id = null - 若需高效获取整棵树(如后台菜单),建议后续配合 laravel-nestedset 扩展,但其迁移结构不同(需额外字段:
_lft,_rgt);纯自引用适合中小规模、读多写少场景 - 迁移后别忘了运行:
php artisan migrate
模型中定义关联(快速验证结构)
迁移完成后,在 app/Models/Category.php 中添加:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Category extends Model
{
protected $fillable = ['name', 'slug', 'parent_id', 'order_column', 'is_active'];
public function children(): HasMany
{
return $this->hasMany(Category::class, 'parent_id');
}
public function parent(): BelongsTo
{
return $this->belongsTo(Category::class, 'parent_id');
}
// 获取所有祖先(向上递归)
public function ancestors()
{
return $this->parent()->with('ancestors');
}
// 获取所有后代(向下递归,适用于小数据量)
public function descendants()
{
return $this->children()->with('descendants');
}
}
不复杂但容易忽略:迁移只是铺路,真正实现“无限级”靠的是模型关系 + 查询逻辑(如递归集合、Eloquent 加载、或前端树形组件配合 API 层整理)。先确保字段扎实,再叠加业务逻辑更稳。


















