php 如何生成path及其日常维护

path字段重要性不言而喻,在查询的时候,如果只用pid,查询效率会很低,增加path,查询效率大大提高,最起码不用递归查库了,重点是维护推荐关系的时候要维护path以及更改。

在path分隔符中,建议使用英文','号,方便查询。切记使用like,最好是使用find_in_set

一、path字段

1、首先是在会员表中,得有path字段,一些情况下,path字段会比较长,建议类型为text,不建议varchar

2、当推荐新会员的时候,借助父级的path,后面拼接上父级的id,就是新会员的path

1 $path = $path ? $pid . ',' . $path : $pid;

二、后台修改推荐人

这种情况是比较麻烦的,就是后台想更改某会员的父级,如果单纯的只有pid,只更改pid就行了,但是存在path,更改当前会员pid和path的同时,当前会员所有团队成员的path也得更改。

这里存在当前会员之前有上级和之前没有上级两种情况

1、已有上级,这时候所有团队成员的path为当前会员新path再拼接上当前会员的id,再拼接上下级之前的path中截取当前用户id之后的部分

2、没有上级,那所有团队成员的新path就简单了,直接为当前会员新path,直接拼接上下级的path即可

 1 if ($params['pid'] && $params['pid'] != $row['pid']) {
 2     //说明选择了新上级,而且确实和之前上级不一样了,如果新上级和之前上级一样,无需更新path
 3     //首先验证pid不在目标子串中
 4     $arr = explode(',',$puser['path']);
 5     if ($arr && in_array($ids,$arr)) {
 6         $this->error('自己下级不能成为新上级');
 7     }
 8     //更新当前会员自己的pid和path,
 9     $params['path'] = $puser['path'] ? $puser['path'] . ',' . $params['pid'] : $params['pid'];
10     if ($row['pid']) {
11         //说明当前会员之前就有上级,
12         //则所有下级的新path为$params['path'] 再拼接上当前会员的id,再拼接上下级之前的path中截取当前用户id之后的部分
13         $sql = "update sn_user set path = (CONCAT('".$params['path']."',',',".$ids.",SUBSTRING_INDEX(path,".$ids.",-1))) where FIND_IN_SET(".$ids.",path)";
14     } else {
15         //说明当前会员之前没有上级,那所有下级的新path就简单了,直接为$params['path'],直接拼接上下级的path即可
16         $sql = "update sn_user set path = (CONCAT('".$params['path']."',',',path)) where FIND_IN_SET(".$ids.",path)";
17     }
18     $this->model->query($sql);
19 } else {
20     unset($params['pid']);
21 }

三、在无path下如何增加path

这种情况一般发生在已有一些会员的情况下,如果会员不多,自己手动改就行,当然,如果会员量比较大的话,手动就费劲了,所以有时候写一个脚本也是挺管用的。

1、首先在会员表新增path字段,默认为空值,然后新建一个标识path_status,在会员量大的时候进行分段查询

2、借助脚本,更新path,这里写的了一个递归查询,如有更好的方法,欢迎留言交流!

 1 /*
 2  * 更新path字段
 3  */
 4 public function update_path()
 5 {
 6     //更新所有的用户的path]
 7     $users = Db::name('member')
 8         ->where([
 9             'pid'=>['gt',0],
10             'path_status'=>0,
11         ])
12         ->field('id,pid,path')
13         ->limit(100)->select();
14     $count = 0;
15     foreach ($users as $v) {
16         //计算path,修改path_status为1
17         $path = $this->get_path(0,$v['pid']);
18         //$path = '0-'.$path;//拼接上顶级0
19         Db::name('member')->where('id',$v['id'])->update(['path'=>$path,'path_status'=>1]);
20         $count++;
21     }
22     echo $count;die;
23 }

这里是获取path的方法:

 1 /*
 2  * 递归查库,获取上级pid
 3  */
 4 public function get_path($path,$pid)
 5 {
 6     $path = $path ? $pid.'-'.$path : $pid;
 7     $rid = Db::name('member')->where('id',$pid)->value('pid');
 8     if ($rid) {
 9         return self::get_path($path,$rid);
10     }
11     return $path;
12 }

如果对于path的实现,有更好的方法或思路,欢迎留言交流!

12-23 13:03