Laravel中whereIn查询如何保持传入数组的原有排序
实现方法
满足「不逐条查询、不新增数据库排序字段」要求的实现方案共两种,可根据项目场景选择:
方案1:数据库原生排序(推荐,性能最优)
利用数据库的自定义排序函数在查询阶段直接完成排序,返回结果即为目标顺序,无后续处理开销。
MySQL/MariaDB 实现
使用FIELD()函数自定义排序规则,修改组件构造方法内的查询逻辑即可:
<?php namespace App\View\Components; use App\Models\JobState; use Illuminate\Support\Facades\DB; // 引入DB门面 use Illuminate\View\Component; class StatusDropdown extends Component { public $states; public function __construct() { $targetIds = [4, 5, 10, 3, 11]; $this->states = JobState::whereIn('id', $targetIds) ->orderByRaw(DB::raw('FIELD(id, ' . implode(',', $targetIds) . ')')) ->get(); } /** * Get the view / contents that represent the component. * * @return \Illuminate\Contracts\View\View|\Closure|string */ public function render() { return view('components.status-dropdown'); } }
PostgreSQL 实现
若使用PostgreSQL数据库,将orderByRaw部分替换为如下语法即可:
->orderByRaw('array_position(ARRAY[?]::int[], id)', [$targetIds])
方案2:集合排序(数据库无关,兼容性最强)
如果需要兼容SQLite等不支持上述原生排序函数的数据库,可在查询完成后,通过Laravel集合的排序方法按目标ID顺序重排结果:
<?php namespace App\View\Components; use App\Models\JobState; use Illuminate\View\Component; class StatusDropdown extends Component { public $states; public function __construct() { $targetIds = [4, 5, 10, 3, 11]; $this->states = JobState::whereIn('id', $targetIds) ->get() ->sortBy(fn($state) => array_search($state->id, $targetIds)) ->values(); // 重置集合键,避免前端循环时索引异常 } /** * Get the view / contents that represent the component. * * @return \Illuminate\Contracts\View\View|\Closure|string */ public function render() { return view('components.status-dropdown'); } }
注意:末尾必须调用
values()方法重置集合键。sortBy处理后会保留原集合的数字键,若不重置,前端@foreach循环时可能出现索引不连续导致的渲染异常。
两种方案都仅需一次批量查询,不需要修改数据表结构,视图层代码无需任何调整即可直接按指定顺序渲染下拉选项。
内容的提问来源于stack exchange,提问作者ThurstonLevi
相关产品推荐
相关产品推荐

