如何在Laravel中无需逐函数编码实现Controller所有方法自动打info日志
实现控制器方法自动日志记录的方案(基于Laravel框架)
针对你提到的场景,推荐两种常用的无侵入实现方案,不需要修改每个控制器的业务方法:
方案1:重写控制器基类callAction方法(适配所有继承基类的控制器)
Laravel框架所有控制器方法执行时都会调用基类的callAction方法,直接重写该方法即可全局植入日志逻辑:
- 打开项目基类控制器文件
app/Http/Controllers/Controller.php,添加如下代码:
<?php namespace App\Http\Controllers; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; use Illuminate\Support\Facades\Log; class Controller extends BaseController { use AuthorizesRequests, ValidatesRequests; // 重写callAction方法植入日志逻辑 public function callAction($method, $parameters) { // 仅开发环境记录日志,生产环境可关闭 if (!app()->environment('local')) { return parent::callAction($method, $parameters); } $actionTag = static::class . '@' . $method; // 记录方法启动和入参,可自行过滤password、token等敏感字段 Log::info("Start {$actionTag}", $this->filterSensitiveParams($parameters)); // 执行原业务逻辑 $result = parent::callAction($method, $parameters); // 记录方法结束和返回结果,二进制/文件响应可跳过记录内容 Log::info("End {$actionTag}", [ 'result' => is_string($result) || is_array($result) || is_object($result) ? $result : 'unrecorded type' ]); return $result; } // 敏感参数过滤,可自定义需要过滤的字段 private function filterSensitiveParams(array $params): array { $sensitiveKeys = ['password', 'password_confirmation', 'api_token', 'access_token']; foreach ($params as $key => $value) { if (in_array($key, $sensitiveKeys)) { $params[$key] = '***'; } } return $params; } }
该方案的优势是零额外配置,所有继承该基类的控制器方法都会自动记录日志,不需要修改路由或者业务代码。
方案2:使用路由中间件(适配指定路由组)
如果你只需要给部分路由对应的控制器记录日志,可以用中间件实现:
- 生成中间件文件:
php artisan make:middleware LogControllerAction
- 编辑中间件文件
app/Http/Middleware/LogControllerAction.php:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Log; class LogControllerAction { public function handle($request, Closure $next) { if (!app()->environment('local')) { return $next($request); } $action = $request->route()->getAction(); $actionTag = $action['controller'] ?? 'UnknownController@unknownMethod'; // 记录请求入参 Log::info("Start {$actionTag}", $this->filterSensitiveParams($request->all())); $response = $next($request); // 记录返回结果 Log::info("End {$actionTag}", [ 'result' => $response->original ?? $response->getContent() ]); return $response; } private function filterSensitiveParams(array $params): array { $sensitiveKeys = ['password', 'password_confirmation', 'api_token', 'access_token']; foreach ($params as $key => $value) { if (in_array($key, $sensitiveKeys)) { $params[$key] = '***'; } } return $params; } }
- 注册中间件,打开
app/Http/Kernel.php,将中间件添加到需要的路由组中:
protected $middlewareGroups = [ 'web' => [ // 其他中间件 \App\Http\Middleware\LogControllerAction::class, ], 'api' => [ // 其他中间件 \App\Http\Middleware\LogControllerAction::class, ], ];
也可以单独给指定路由绑定中间件,灵活控制日志覆盖范围。
注意事项
- 如果返回结果是文件、二进制流等大体积内容,建议跳过结果记录,避免日志文件过大
- 生产环境建议关闭该类调试日志,或者将日志级别调整为debug,避免占用过多存储
- 敏感字段一定要做过滤,避免密码、密钥等信息泄露到日志中
内容的提问来源于stack exchange,提问作者Thinh Nguyen
相关产品推荐
相关产品推荐

