path enumeration 是用字符串(如"1/3/8/12")存储节点完整路径的树形结构实现方式;它无需额外表或左右值,查询子树用 like 'x/y/%',适合读多写少、层级浅且节点移动少的场景。

Path Enumeration 是什么,为什么不用 Nested Set 或 Closure Table
Path Enumeration(路径枚举)不是 Eloquent 原生支持的模型关系模式,它指的是用字符串(如 "1/3/8/12")在数据库字段中直接存储节点的完整路径。相比 NestedSet 扩展或 ClosureTable,它没有额外表、不依赖左右值维护,查询子树只需 LIKE '1/3/%',写入快、逻辑透明——但你要自己保证路径格式一致、更新时手动重算子路径。
它适合读多写少、层级不深(depth ≤ 6)、不需要频繁移动节点的场景,比如后台菜单、静态分类、地区三级联动。
如何在 Laravel 模型中实现路径生成与查询
关键不是“用哪个包”,而是控制好 path 字段的生成时机和格式。不要依赖事件自动拼接,而应在保存前显式处理:
- 父节点存在时,用
$parent->path . '/' . $this->id;根节点设为$this->id(不是"1"或空字符串) - 必须在
creating事件里赋值,避免重复插入时路径错乱 - 路径字段建议设为
VARCHAR(255),并加索引(INDEX(path)),MySQL 的前缀索引对LIKE 'xxx%'有效
class Category extends Model
{
protected $fillable = ['name', 'parent_id', 'path'];
<pre class="brush:php;toolbar:false;">protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if ($model->parent_id) {
$parent = static::find($model->parent_id);
$model->path = $parent->path . '/' . $model->id;
} else {
$model->path = (string) $model->id;
}
});
}}
查询子树、祖先、同级节点的写法和陷阱
所有基于路径的查询都依赖字符串匹配,但 MySQL 的 LIKE 对前导通配符(%xxx)无法走索引,所以只写 path LIKE '1/3/%',别写 path LIKE '%/3/%'。
- 查所有子节点(含自身):
Category::where('path', 'like', $node->path . '/%')->get() - 查直接子节点(仅下一级):
Category::where('path', 'like', $node->path . '/%')->whereRaw('LENGTH(path) - LENGTH(REPLACE(path, "/", "")) = ?', [$node->depth + 1])->get() - 查祖先(从路径拆分 ID 数组再批量查):
array_map(fn($id) => Category::find($id), explode('/', $node->path))—— 注意空字符串风险,explode('/', '1')返回['1']没问题,但explode('/', '')返回['']会查出意外结果
移动节点时 path 必须批量更新,且不能用事务外操作
这是最容易出错的地方:把节点 A 从路径 "1/3" 移到 B 下(B 路径是 "1/5"),不仅要改 A 的 path 和 parent_id,还要把 A 的所有后代路径全量替换 —— UPDATE categories SET path = REPLACE(path, '1/3/', '1/5/' || id) WHERE path LIKE '1/3/%'; 这种写法在 PostgreSQL 可行,但 MySQL 不支持表达式拼接,得用 PHP 循环 + update()。
- 必须用事务包裹:先查出所有需更新的后代,再逐条更新其
path,最后更新节点自身 - 禁止在模型事件里触发另一次 save(会导致无限递归或死锁)
- 路径中的 ID 是整数,但拼成字符串后比较,所以
"12"和"1/2"不冲突;但若用短 ID(如"1")做前缀,要警惕"10"被误认为"1"的子路径,建议统一补零或用定长分隔符(如"|1|3|8|")
路径不是银弹。一旦业务需要频繁拖拽排序、跨树迁移、或层级动态很深,就该切回 NestedSet;而 Path Enumeration 真正省心的地方,只在你接受“写入由人控、查询靠字符串、绝不混用多种模型树方案”这三条约束。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











