Laravel:如何在listen方法中统计受影响行数及修改列数?
获取Laravel中UPDATE/DELETE查询的修改列数(或受影响行数)
嘿,这个需求我刚好处理过,给你分享一下实现思路和代码!
首先要明确两个关键点:
- UPDATE语句:确实存在「被修改的列数量」,也就是SQL中
SET子句里的列个数 - DELETE语句:它是删除行的操作,并不会修改任何列,所以这里你可能是想获取被删除的行数(受影响行数),我会一起说明两种情况的实现方式。
实现代码
use Illuminate\Support\Facades\Log; \DB::listen(function ($q) { $sql = strtolower(trim($q->sql)); // 处理UPDATE类型查询 if (str_starts_with($sql, 'update')) { // 正则匹配SET子句内容,兼容带WHERE/LIMIT的情况 preg_match('/set\s+(.*?)\s+(where|limit|$)/i', $sql, $matches); if (isset($matches[1])) { // 分割列项,避免把字符串值中的逗号误判为列分隔符 $columnEntries = preg_split('/,(?=(?:[^"]*"[^"]*")*[^"]*$)/', $matches[1]); $modifiedColumnCount = count($columnEntries); // 记录到日志,你也可以改成自己的存储逻辑 Log::info("UPDATE操作修改了 {$modifiedColumnCount} 个列", [ '原始SQL' => $q->sql, '绑定参数' => $q->bindings, '执行时间' => $q->time . 'ms' ]); } } // 处理DELETE类型查询 elseif (str_starts_with($sql, 'delete')) { // DELETE操作获取受影响的行数(即被删除的行数) $affectedRows = $q->affected; Log::info("DELETE操作删除了 {$affectedRows} 行数据", [ '原始SQL' => $q->sql, '绑定参数' => $q->bindings, '执行时间' => $q->time . 'ms' ]); // 如果确实需要强调「无修改列」,可以添加这条日志 // Log::info("DELETE操作未修改任何列", ['SQL' => $q->sql]); } });
关键细节说明
- 查询类型判断:用
str_starts_with配合转小写的SQL,避免大小写敏感问题(比如Update或DELETE开头的语句也能匹配) - UPDATE列数统计:
- 用正则提取
SET到WHERE/LIMIT/语句结尾之间的内容,确保只拿到列赋值部分 - 分割列项时用的正则
/(?=(?:[^"]*"[^"]*")*[^"]*$)/,可以跳过字符串值中的逗号(比如name = "Smith, Alice"这种情况不会被误分割)
- 用正则提取
- DELETE受影响行数:Laravel的
$q对象自带affected属性,直接就能拿到被删除的行数,非常方便
内容的提问来源于stack exchange,提问作者Sebastián Daza
相关产品推荐
相关产品推荐

