PHP Laravel中获取任意父用户的子级及多级子级(MLM系统)
解决MLM系统多级下线用户递归查询问题
原代码存在的核心问题
- 递归逻辑混乱:使用
while($depth-- != 0)嵌套递归,导致层级重复处理,无法正确遍历所有子级。 - 数组传递失效:PHP数组默认值传递,递归内修改的
$ids无法同步到上层,最终无法收集全量下线ID。 - 结果未赋值:
search_result变量未定义,视图无法获取下线用户数据。 - Depth计算不合理:依赖全局最大depth控制递归次数,易因数据变动出现错误,且无法适配动态层级结构。
修正后的代码实现
控制器方法:searchAllDownline
public function searchAllDownline(Request $req){ $req->validate(['search_keyword'=>'required']); $search_keyword = $req->search_keyword; $position = $req->position; $user = User::where('username',$search_keyword)->first(); if(empty($user)){ return back()->with('error','无效的用户名'); } // 获取当前用户的直接子级ID $downlineIds = User::where('parent_id', $user->id) ->where('position', $position) ->pluck('id') ->toArray(); // 递归获取所有多级子级ID $this->recursion($downlineIds, $position); // 查询所有下线用户的完整数据 $search_result = User::whereIn('id', $downlineIds)->get(); return view('admin.all-downline',compact('search_result','search_keyword','position')); }
递归方法:recursion
public function recursion(&$ids, $position){ // 获取当前ID集合对应的子级用户ID $subIds = User::whereIn('parent_id', $ids) ->where('position', $position) ->pluck('id') ->toArray(); if(empty($subIds)){ // 无下级用户,终止递归 return; } // 将子级ID合并到主集合 $ids = array_merge($ids, $subIds); // 递归处理新获取的子级ID $this->recursion($ids, $position); }
关键优化点说明
- 引用传递数组:通过
&$ids确保递归过程中对数组的修改能同步到上层调用,避免数据丢失。 - 自然终止递归:移除固定depth限制,当查询不到子级用户时自动终止递归,适配任意层级的MLM结构。
- 简化ID收集:使用
pluck('id')直接提取ID数组,替代手动循环赋值,代码更高效简洁。 - 完善结果传递:新增
search_result变量,通过whereIn查询全量下线用户数据,确保视图能获取到所需内容。
更简洁的Laravel关联实现(可选)
如果你的User模型支持关联定义,可以直接用递归关联替代手动递归:
User模型添加关联方法
public function downline($position = null){ $query = $this->hasMany(User::class, 'parent_id'); if($position){ $query->where('position', $position); } // 预加载多级子级 return $query->with(['downline' => function($q) use ($position){ if($position){ $q->where('position', $position); } }]); }
控制器中调用关联
// 替换原递归逻辑,直接获取所有多级下线用户 $search_result = $user->downline($position)->get()->flatten();
内容的提问来源于stack exchange,提问作者Saim Khan
相关产品推荐
相关产品推荐

