
Laravel 原生 DB 门面不支持直接获取存储过程返回的多个结果集;需借助扩展包(如 rodion-arr/laravel-mysql-stored-procedures)或底层 PDO 多结果集处理机制来实现全量数据提取。
laravel 原生 db 门面不支持直接获取存储过程返回的多个结果集;需借助扩展包(如 `rodion-arr/laravel-mysql-stored-procedures`)或底层 pdo 多结果集处理机制来实现全量数据提取。
在使用 MySQL 存储过程时,若其内部通过多个 SELECT 语句返回多个结果集(例如分别查询用户统计、订单汇总、库存状态等),Laravel 默认的 DB::select() 方法将仅捕获第一个结果集——这是由 PDO 驱动限制及 Laravel 封装逻辑共同导致的。正如你在 phpMyAdmin 中看到的完整多表格输出,在 Laravel 中却只得到 {"operation4":7185,"operation5":18167} 这样的单结果响应,根本原因在于:DB::select() 底层调用的是 PDO::query() 或 PDO::execute(),而它们默认不启用多结果集遍历(multi-result set fetching)。
要真正获取全部结果集,有两种可靠方案:
✅ 方案一:使用专用扩展包(推荐用于快速落地)
laravel-mysql-stored-procedures 是专为解决此问题设计的轻量级包,它封装了 PDO 的 nextRowset() 逻辑,自动遍历并结构化所有结果集。
安装与使用示例:
composer require rodion-arr/laravel-mysql-stored-procedures
在控制器中调用:
use RodionArr\LaravelMysqlStoredProcedures\StoredProcedure;
$resultSets = StoredProcedure::call('MY_PROC', [$param1, $param2]);
// $resultSets 是一个数组,每个元素对应一个结果集(二维数组)
return response()->json([
'dt1' => $resultSets[0] ?? [],
'dt2' => $resultSets[1] ?? [],
'dt3' => $resultSets[2] ?? [],
], 200);该包会自动处理 PDO::nextRowset() 循环,并将每个结果集转为关联数组集合,兼容 Laravel 9+ 和 MySQL 5.7+/8.0。
✅ 方案二:原生 PDO 手动处理(适合深度定制场景)
若倾向零依赖方案,可绕过 DB 门面,直接操作底层 PDO 实例:
use Illuminate\Support\Facades\DB;
$pdo = DB::getPdo();
$statement = $pdo->prepare('CALL MY_PROC(?, ?)');
$statement->execute([$param1, $param2]);
$resultSets = [];
do {
$resultSet = $statement->fetchAll(PDO::FETCH_ASSOC);
if ($resultSet !== false) {
$resultSets[] = $resultSet;
}
} while ($statement->nextRowset()); // 关键:推进到下一个结果集
return response()->json(['all_results' => $resultSets], 200);⚠️ 注意事项:
- 确保 MySQL 配置中 mysqli.reconnect = Off(默认安全),避免连接复用干扰多结果集;
- 存储过程中禁止使用 SELECT ... INTO @var 等非结果集语句,否则可能中断 nextRowset() 遍历;
- 若存储过程含 OUT 或 INOUT 参数,需改用 PDO::bindParam() 显式绑定,本例未涉及可忽略;
- Laravel Telescope 或 Query Log 可能无法完整记录多结果集调用,建议结合数据库日志验证。
✅ 总结:Laravel 原生不支持多结果集是设计取舍而非缺陷。生产环境推荐使用经验证的扩展包以保障稳定性与可维护性;自研 PDO 方案适用于有特殊事务控制或审计需求的场景。无论哪种方式,核心都在于主动调用 nextRowset() 并循环提取,而非依赖单次 fetch*()。










