如何将指定原生SQL查询转换为Eloquent以实现分页功能?
方案1:转换为Eloquent/查询构造器写法实现分页
你的原始SQL逻辑本质是获取「用户创建的项目」+「用户通过district_group_project_users关联的项目」的并集,去重后返回完整项目数据,转换为Laravel查询构造器/Eloquent写法后可直接调用内置分页方法:
// 子查询1:获取用户关联的项目ID $sub1 = DB::table('district_group_project_users') ->where('user_id', $id) ->select('project_id as id'); // 子查询2:获取用户创建的项目ID $sub2 = DB::table('projects') ->where('created_by', $id) ->select('id'); // 合并两个子查询并去重,和原SQL逻辑完全对齐 $unionSub = $sub1->unionAll($sub2)->distinct(); // 写法1:查询构造器直接分页,返回stdClass类型的项目数据 $projects = DB::table('projects') ->joinSub($unionSub, 'sub', 'sub.id', '=', 'projects.id') ->paginate(10); // 括号内参数为每页展示条数,可自定义 // 写法2:Eloquent模型分页,前提是你已经创建了Project Eloquent模型,返回模型实例 $projects = \App\Models\Project::joinSub($unionSub, 'sub', 'sub.id', '=', 'projects.id') ->paginate(10);
上述写法返回的分页实例和Laravel默认paginate方法返回的实例完全一致,可直接调用links()渲染分页组件。
方案2:不改动原始SQL的原生查询分页方案
如果不想调整原SQL逻辑,可以手动通过LengthAwarePaginator实现分页:
use Illuminate\Pagination\LengthAwarePaginator; $perPage = 10; // 每页条数 $page = request()->input('page', 1); // 读取当前页码,默认第1页 $offset = ($page - 1) * $perPage; // 计算查询偏移量 // 查询符合条件的总条数 $total = DB::select( "SELECT COUNT(*) as count FROM projects INNER JOIN(select DISTINCT * from (SELECT project_id FROM district_group_project_users where user_id=? UNION ALL select id from projects where created_by=?) as sub ) as sub on sub.project_id=projects.id", [$id, $id] )[0]->count; // 给原SQL加分页限制,查询当前页数据 $projects = DB::select( "select * from projects INNER JOIN(select DISTINCT * from (SELECT project_id FROM district_group_project_users where user_id=? UNION ALL select id from projects where created_by=?) as sub ) as sub on sub.project_id=projects.id LIMIT ? OFFSET ?", [$id, $id, $perPage, $offset] ); // 实例化分页器,使用效果和内置paginate方法完全一致 $projects = new LengthAwarePaginator( $projects, $total, $perPage, $page, ['path' => request()->url(), 'query' => request()->query()] );
注意:两种方案都采用了参数绑定传入用户ID,避免直接拼接SQL产生的注入风险,请勿使用原始代码里的字符串拼接写法。
内容的提问来源于stack exchange,提问作者ismail khan
相关产品推荐
相关产品推荐

