You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8 如何合并集合与查询构建器后使用分页功能

错误原因

union() 方法仅支持接收另一个查询构建器实例作为入参,你的代码中$processingRequests调用了get()方法后已经转为Collection集合对象,传入union()就会触发类型不匹配的报错。

解决方案

提供两种适配不同场景的实现方式:

方案一:重构逻辑使用原生SQL union(性能最优,优先选择)

如果FormsController::checkUserPermissionToConsultForm的权限校验逻辑可以转化为SQL查询条件,就不要提前调用get(),让两个变量都保持查询构建器实例,直接用原生union后分页即可:

public function getRequests(){
    $closedRequests = request::join('request_logs', 'request_logs.request_id', '=', 'requests.id')
        ->select("requests.id", "requests.user_id", "requests.form_type", "requests.created_at", "requests.request_status")
        ->whereNotIn('request_status', [-2, 0])
        ->where('request_logs.user_id', Auth::user()->id);

    $processingRequests = request::select("requests.id", "requests.user_id", "requests.form_type", "requests.created_at", "requests.request_status")
        ->where('request_status', 0)
        // 此处将权限校验逻辑转化为SQL where条件,例:关联权限表做存在判断等
        ->whereRaw(/* 转化后的权限判断SQL逻辑 */);

    $result = $closedRequests->union($processingRequests)
        ->orderBy('created_at', 'desc')
        ->paginate(5);
    return $result;
}

方案二:合并集合后手动生成分页器(适配权限逻辑无法转SQL的场景)

如果权限校验必须在PHP层处理,就先执行两个查询拿到集合,合并后手动实例化分页对象:

public function getRequests(){
    // 执行第一个查询拿到集合
    $closedRequests = request::join('request_logs', 'request_logs.request_id', '=', 'requests.id')
        ->select("requests.id", "requests.user_id", "requests.form_type", "requests.created_at", "requests.request_status")
        ->whereNotIn('request_status', [-2, 0])
        ->where('request_logs.user_id', Auth::user()->id)
        ->get();

    // 执行第二个查询并做权限过滤
    $processingRequests = request::select("requests.id", "requests.user_id", "requests.form_type", "requests.created_at", "requests.request_status")
        ->where('request_status', 0)
        ->get()
        ->filter(function ($request) {
            return FormsController::checkUserPermissionToConsultForm($request, true);
        });

    // 合并集合、去重、排序
    $allRequests = $closedRequests->merge($processingRequests)
        ->unique('id')
        ->sortByDesc('created_at');

    // 手动分页参数处理
    $perPage = 5;
    $currentPage = request()->input('page', 1);
    $currentPageItems = $allRequests->slice(($currentPage - 1) * $perPage, $perPage)->values();

    // 生成分页器
    $paginatedResult = new \Illuminate\Pagination\LengthAwarePaginator(
        $currentPageItems,
        $allRequests->count(),
        $perPage,
        $currentPage,
        [
            'path' => request()->url(),
            'query' => request()->query()
        ]
    );

    return $paginatedResult;
}

注意:方案二需要一次性查询所有符合条件的数据再做切割,数据量较大时性能较差,仅适用于数据量可控的场景。

内容的提问来源于stack exchange,提问作者Achraf Ben Soltane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 15:15:03