再谈无限极分类,这次是左右值

上篇博客里面说了一下无限分类,其中用国民级算法递归和巧妙引用来取值的方法都有,然后抱着对无限分类感兴趣的心理,上网学习发现还有左右值大法,因为本人不是计算机专业的,所以觉得这种方法非常的好玩,一番研究之后,分享一下这个左右值大法。

什么是左右值

上一篇博客中,有这样的一个分类,这个分类众所周知是通过PID方式来实现内部分类逻辑的
再谈无限极分类,这次是左右值_第1张图片
同样的几条数据,我们换一种方式,这次引入左右值
再谈无限极分类,这次是左右值_第2张图片
初看之下感觉非常的紊乱,来细细的捋一下,跟着左右值走一下

从1开始:
后台首页(1)→数据一览(2,3)→更新日志(4,5)→添加日志(6,7)→后台首页(8)

看出问题来了吗?凡是在1-8中间的左右值,都是属于这个分类的子分类,明白了这其中的关系,接下来再进一步的利用这种神奇的左右值进行操作

根据左右值查找数据

纯天然获取已经排序好的分类数据

$sql = "select * from sp_auth_bak order by auth_left"

结合左右值的特性可以很容易的通过这样一条简单的sql指令获取到已经排好序的分类数组,仅仅一次查询操作而已,左右值的魅力初步体现,不再需要后期的递归,不需要任何多余的操作,只需要按照左值顺序排序,一定是排序好的结果

查找某个分类的下属分类

这个也是很简单的,比如我们要找到后台首页的所有后代分类,首先取得它的左右值分别是1,8,那么则有,查找左右值在这个范围内的数据就行,

select * from sp_auth_bak where auth_left between 1 and 8 order by auth_left

是不是非常的简单粗暴,真是省去了很多后期处理数据的烦恼

查找某个分类的路径

这个其实也很简单,它的父级分类,必定同时满足两个条件,左值小于待查找分类的左值,右值则是大于,sql就不写了

获取某个分类的后代分类的数量

通常的思路是利用count,这里其实很简单的通过(右值-左值-1)/2就可以得到数量,为什么呢?

根据左右值来插入数据

前面看来,查找数据确实很方便,但是如果需要插入一条数据呢,举个例子,我们在“添加日志<6,7>” 下面添加一个新的分类叫做 “添加更新日志
现在来分析一下,需要什么操作

  1. 新添加的数据,因为属于“添加日志<6,7>”,那么根据左右值的构造,这条新的数据,应该是这样的—–添加更新日志<8,9>
  2. 查看现在的表结构可以知道,从7以后的左右值都已经被占据了,如果强行插入的话,现有的表结构肯定混乱
  3. 所以!需要给<8,9>腾出两个位置,也就是说,所有比7大的左右值,全部加2
$sql = "update sp_auth_bak set auth_left = auth_left + 2 where auth_left >=7 ";
$sql = "update sp_auth_bak set auth_right = auth_right + 2 where auth_right >=7 ";

经过这一步操作后,现在的表结构应该是这样的
再谈无限极分类,这次是左右值_第3张图片
4. 万事俱备,接下来将<8,9>插入,完美收工

$sql = "insert into sp_auth_bak value(null,'添加更新日志',7,8,2)";//最后一个2是为了前台处理缩进的时候有个依据,这里的2是等于父分类的level值加1

再谈无限极分类,这次是左右值_第4张图片

接下来,只要查找左值在1-10之间的数据就能得到后台首页的所有后代分类了,在读取数据上,依然还是一条简单的sql就可以搞定了

修改某个数据的所属分类呢?

如何根据左右值来修改呢,这里,其实可以看出来某些问题了,这也是左右值一个尴尬的地方,不过话说回来,在这里的话,个人的解决办法是两步走

  1. 删除待修改的分类,(为什么是删除呢?),将当前分类后面的左右值全部减2
  2. 复用之前的插入数据操作,所以在第一步执行删除,这样这里可以直接复用插入函数或者方法,而不是另外选择重新写一个更新方法

后记

从上面可以看出来,虽然左右值在读取数据方面具有很大的优势,但是如果需要频繁的增删改,实际左右值的操作步骤还是挺多的,在这里有一个解决办法,将左右值加减2的操作放在一些框架的钩子函数或者mysql的触发器里面,在执行增删改的时候自动调用这种操作

可以看到,如果需要频繁的增删改,用PID的方式依然是很简便的,而如果需要频繁的读取大批量的分类数据,因为左右值没有递归操作,所以效率很高。

下面引入一个函数,将已有的PID表结构更新为左右值结构,在现有的表结构上增加左右值字段之后,执行函数。实际操作起来,需要修改里面的一些参数,或者自己再进行进一步的封装,这里是使用PDO做的操作

/**将父子结构变成左右值结构的函数  数据库相关的参数例如表名字段自己修改
** @param int $pid 顶级分类的父ID
** @param int $left 从哪个左值开始排列,最终结果起始左值会等于$left+1,因为无论如何都会递归1** @param pdo $dbh 一个pdo资源,如果在tp框架,可以是一个model
*/
function getTree($pid,$left,$dbh)
{
    $right = $left + 1;
    $result = $dbh->query("
        SELECT auth_id
        FROM sp_auth_copy
        WHERE auth_pid = '" . $pid . "'
        ;"
    );
    foreach ($result as  $row) {
        var_dump($row["auth_id"]);
        $right = getTree($row['auth_id'], $right,$dbh);
    }
    $dbh->exec("
        UPDATE sp_auth_copy
        SET
            lft = '" . $left . "',
            rgt= '" . $right . "'
        WHERE auth_id = '" . $pid . "'
        ;"
    );
    return $right+1;
}

有了这种函数之后,可以有巧妙的办法,那就是执行增删改的时候,用PID的方式执行,而在增删改之后,调用这个函数,更新左右值,而前台等地方需要读取分类的时候,就使用左右值,当然,函数的调用依然是可以放在触发器或者钩子函数里面的

你可能感兴趣的:(再谈无限极分类,这次是左右值)