如何在Laravel递归关联中设置动态orderBy查询参数
实现递归关联的动态排序字段
方法1:利用模型属性动态指定排序字段
给模型加一个可修改的属性,默认值设为原来的name,不影响原有逻辑:
class YourModel extends Model { // 动态排序字段,默认值为'name' public $orderByField = 'name'; public function children() { return $this->hasMany(self::class, 'parent_id', 'id') ->orderBy($this->orderByField) ->with(['children' => fn($q) => $q->orderBy($this->orderByField)]); } }
使用时直接给模型实例设置字段就行:
// 按'created_at'排序 $model = YourModel::first(); $model->orderByField = 'created_at'; $tree = $model->children; // 或者查询前直接设置 $tree = YourModel::where('id', 1)->first()->setAttribute('orderByField', 'sort_order')->children;
方法2:用静态变量全局临时设置
如果需要某次请求里所有递归关联都用同一个字段排序,可以用静态变量配合静态方法:
class YourModel extends Model { protected static $tempOrderByField = 'name'; // 静态方法用来设置排序字段 public static function setRecursiveOrderBy(string $field) { static::$tempOrderByField = $field; } public function children() { return $this->hasMany(self::class, 'parent_id', 'id') ->orderBy(static::$tempOrderByField) ->with(['children' => fn($q) => $q->orderBy(static::$tempOrderByField)]); } }
使用示例:
// 设置按'sort_order'排序 YourModel::setRecursiveOrderBy('sort_order'); // 获取树结构数据 $tree = YourModel::with('children')->get(); // 用完可以重置回默认值(可选) YourModel::setRecursiveOrderBy('name');
方法3:自定义关联方法,灵活传参
要是需要更灵活的控制,比如不同查询用不同字段,也可以给关联方法加参数:
class YourModel extends Model { public function children($orderByField = 'name') { return $this->hasMany(self::class, 'parent_id', 'id') ->orderBy($orderByField) ->with(['children' => fn($q) => $q->orderBy($orderByField)]); } }
预加载时要通过闭包指定参数:
// 预加载时指定排序字段为'created_at' $tree = YourModel::with(['children' => fn($q) => $q->orderBy('created_at')])->get(); // 递归层级统一用同一个字段的写法 $orderBy = 'sort_order'; $tree = YourModel::with(['children' => function($q) use ($orderBy) { $q->orderBy($orderBy)->with(['children' => fn($q2) => $q2->orderBy($orderBy)]); }])->get();
内容的提问来源于stack exchange,提问作者MAXIMAN
相关产品推荐
相关产品推荐

