左右值
- 1.优点:查询数据非常方便,极大降低数据库压力,不用传统递归就可以查询
- 2.缺点:更新数据操作较为繁琐
- 3.适用场景:查询较多的情况,但是移动分类的操作非常复杂,消耗过大,尽量不做这个操作,适用于无限级评论
- 4.保持左右值的连续!!! 中间不能有断掉的!!!
数据库:

示例代码
//添加
public function add($name, $parentId = 0)
{
// 如果没有指定父分类ID,则默认为0(根分类)
$parent = \app\common\model\Test::where('id', $parentId)->find();
if (!$parent) {
// 插入根分类,并设置初始的左右值,插入一级分类
\app\common\model\Test::create([
'name' => $name,
'left' => 1,
'right' => 2,
'pid' => 0,
'level' => 1,
]);
return true;
}
// 查找父分类的右值
$right = $parent['right'];
// 更新所有右值大于当前父分类右值的分类的右值
\app\common\model\Test::where('right', '>=', $right)
->setInc('right', 2);
\app\common\model\Test::where('left', '>', $right)
->setInc('left', 2);
// 插入新分类
\app\common\model\Test::create([
'name' => $name,
'left' => $right,
'right' => $right + 1,
'pid' => $parentId,
'level' => $parent->level + 1,
]);
return true;
}
//查询
public function index($pid = 0)
{
//当前节点子孙总数=(当前节点右值-当前节点左值-1)/2
$categoryModel = new \app\common\model\Test();
return $this->displayCategories($pid, $categoryModel);
}
protected function displayCategories($parentId, $categoryModel, $prefix = '')
{
$tree = [];
$categories = $categoryModel->where('pid', $parentId)->order(['left' => 'asc'])->select();
foreach ($categories as $category) {
$children = $this->displayCategories($category['id'], $categoryModel, $prefix . '--');
if ($children) {
$category['children'] = $children; // 将子分类添加到当前分类的children字段
}
$tree[] = $category; // 将当前分类添加到树中
}
return $tree;
}
//删除
public function deleteCategory($categoryId)
{
// 获取要删除的节点信息
$category = \app\common\model\Test::where('id', $categoryId)->find();
if (!$category) {
return false; // 节点不存在
}
// 获取要删除节点的左右值范围
$left = $category->left;
$right = $category->right;
// 计算要移动的节点数(即要删除的范围大小)--子树的宽度
$shift = $right - $left + 1;
// 删除节点及其所有子节点
\app\common\model\Test::where('left', '>=', $left)
->where('right', '<=', $right)
->delete();
// 更新所有右值大于要删除节点右值的节点的左右值
\app\common\model\Test::where('right', '>', $right)
->setDec('right', $shift);
\app\common\model\Test::where('left', '>', $right)
->setDec('left', $shift);
return true;
}
这个图片很有用,可以认真查看
