Laravel Eloquent查询过滤负值结果后如何实现分页
解决方案
方案1(推荐):数据库层直接过滤,原生支持分页
不需要先查询全量数据到内存再做集合过滤,直接在查询阶段就筛选掉剩余天数小于0的逾期记录,后续链式调用paginate()就能正常工作,性能最优、代码最简洁。
因为Days是SQL计算生成的字段别名,用having方法做筛选即可,不需要重复写日期计算逻辑:
$resting_time = DB::table('alquiler') ->join('socio','alquiler.soc_id','=','socio.id') ->join('pelicula','alquiler.pel_id','=','pelicula.id') ->select( 'socio.soc_nombre', 'pelicula.pel_nombre', 'alquiler.created_at', DB::raw("DATEDIFF(alq_fecha_hasta,NOW()) AS Days") ) ->having('Days', '>=', 0) ->orderBy('Days','asc') ->paginate(6);
这个写法和你最初可正常分页的代码逻辑几乎一致,只是多了一行筛选条件,返回的分页对象和之前的用法完全兼容,不需要修改前端分页渲染的代码。
方案2:集合手动分页(仅适用于必须做内存复杂过滤的场景)
如果你的筛选逻辑复杂到无法直接用SQL实现,必须先取全量数据再通过集合方法处理,可以手动调用Laravel内置的分页类实现和paginate()一致的效果:
// 全量查询、过滤、排序 $filteredRecords = DB::table('alquiler') ->join('socio','alquiler.soc_id','=','socio.id') ->join('pelicula','alquiler.pel_id','=','pelicula.id') ->select( 'socio.soc_nombre', 'pelicula.pel_nombre', 'alquiler.created_at', DB::raw("DATEDIFF(alq_fecha_hasta,NOW()) AS Days") ) ->get() ->filter(fn($item) => $item->Days >= 0) ->sortBy('Days'); // 读取分页参数 $perPage = 6; $currentPage = \Illuminate\Pagination\Paginator::resolveCurrentPage(); // 截取当前页的数据 $pageItems = $filteredRecords->forPage($currentPage, $perPage)->values(); // 生成分页对象,和原生paginate返回值用法完全一致 $resting_time = new \Illuminate\Pagination\LengthAwarePaginator( $pageItems, $filteredRecords->count(), $perPage, $currentPage );
注意:该方案会把所有符合条件的记录加载到内存,表数据量超过千条级别时会明显拖慢接口响应,非必要场景优先选择第一种方案。
内容的提问来源于stack exchange,提问作者tellxmaster
相关产品推荐
相关产品推荐

