如何在Laravel中实现两张关联表的自定义状态排序
Laravel自定义状态排序实现方案
1. 控制器层构造排序查询
你需要通过join关联两个表,再使用orderByRaw自定义排序规则实现需求,排序逻辑核心是将匹配decision like 'setuju'的记录赋值为1,未匹配的赋值为0,降序排序后未匹配的Pending状态就会排在顶部。
示例代码如下:
<?php namespace App\Http\Controllers; use App\Models\Fup; use Illuminate\Http\Request; class ApprovalController extends Controller { public function index() { $fups = Fup::join('approvals', 'fups.id', '=', 'approvals.fup_id') // 按需选择要返回的字段,避免字段冲突 ->select('fups.*', 'approvals.decision as approval_status', 'approvals.id as approval_id') // 自定义排序规则:Pending在前,Approve在后 ->orderByRaw("CASE WHEN approvals.decision LIKE '%setuju%' THEN 1 ELSE 0 END DESC") // 可追加其他排序规则,例如下方按审批创建时间倒序 ->orderBy('approvals.created_at', 'DESC') ->get(); return view('approve', compact('fups')); } }
如果decision字段的setuju是精确匹配,将LIKE '%setuju%'修改为= 'setuju'即可提升查询性能。
2. Blade页面渲染
控制器返回的数据集已经是排序完成的状态,直接在approve.blade.php中遍历渲染即可:
<table class="table"> <thead> <tr> <th>业务标题</th> <th>审批状态</th> <th>创建时间</th> </tr> </thead> <tbody> @foreach($fups as $fup) <tr> <td>{{ $fup->title }}</td> <td> @if(Str::contains($fup->approval_status, 'setuju')) <span class="badge bg-success">Approve</span> @else <span class="badge bg-warning">Pending</span> @endif </td> <td>{{ $fup->created_at->format('Y-m-d H:i') }}</td> </tr> @endforeach </tbody> </table>
注意事项
- 若单条fup记录对应多条approval记录,需要在join时增加条件筛选对应fup的最新审批记录,避免出现重复数据
- 数据量较大时可以给
approvals.decision、approvals.fup_id字段添加索引,优化查询速度 - 不推荐使用
with()预加载关联的方式做跨表排序,预加载是分两次查询,无法直接对关联表字段做全局排序
内容的提问来源于stack exchange,提问作者user10459670
相关产品推荐
相关产品推荐

