Skip to content

树结构

Pin 的树结构能力由 Pin\Tree 模块提供,适合菜单、组织架构、分类等层级数据。

TreeModel

php
use Pin\Tree\TreeModel;

class Menu extends TreeModel
{
    protected $table = 'menus';
}

TreeModel 组合了:

  • Pin\Tree\Concerns\HasTree
  • Pin\Models\Concerns\RedisId
  • Pin\Models\Concerns\SoftDeletes

字段约定

树模型默认使用以下字段:

字段说明
id节点 ID
pid父节点 ID,根节点为 0
path节点路径
pathspath 解析后的 ID 数组
level节点层级
sort排序值
name节点名称

创建节点时 bootHasTree() 会自动补齐 idpidpathlevelsort

创建节点

php
$root = Menu::create([
    'name' => '系统管理',
    'pid' => 0,
]);

$child = Menu::create([
    'name' => '用户管理',
    'pid' => $root->id,
]);

path 会根据当前节点和父节点自动生成。

Tree ModelService

树结构服务层继承通用 ModelService,额外处理节点移动和删除前检查:

php
use Pin\Tree\ModelService;

class MenuService extends ModelService
{
    public string $resourceName = '菜单';
}

更新节点时,如果 pid 变化,会重建当前节点和子树路径:

php
app(MenuService::class)
    ->withModel(Menu::class)
    ->update($menu, [
        'pid' => $newParentId,
        'sort' => -1,
    ]);

删除节点前,如果仍存在子节点,会抛出删除失败错误。

TreeFilter

TreeFilter 会在过滤树数据时维护结构完整性:

php
use Pin\Support\Facades\Tree;

$visibleMenus = Tree::filter(
    $menus,
    fn ($menu) => ! $menu->isDisabled()
);

过滤逻辑:

  1. 找出需要隐藏的节点。
  2. 移除隐藏节点及其子树。
  3. 移除过滤后变成空节点的父级。
  4. 返回重新索引后的集合。

排序与展示

树模块还提供导航、关系、路径、变更、展示和排序相关 trait:

  • TreeRelation
  • TreeNavigation
  • TreePath
  • TreeMutation
  • TreePresenter
  • TreeQuery
  • TreeSorter

这些能力通过 HasTree 统一挂载到模型上。