在 Web 应用开发中,错误和异常是不可避免的。Laravel 提供了强大而灵活的异常处理和日志系统,帮助你在开发阶段快速定位问题,在生产环境中优雅地记录错误并通知开发者。本章将详细介绍如何配置异常处理器、自定义错误页面、写入日志以及利用多频道日志进行监控。
Laravel 的所有异常都集中在 App\Exceptions\Handler 类中处理。这个类负责报告异常(记录日志)和渲染异常(转换为 HTTP 响应)。你可以根据异常类型自定义行为。
在 report 方法中,你可以决定哪些异常需要记录,或向外部服务发送告警。
// 在 App\Exceptions\Handler 中
public function report(Throwable $e)
{
if ($e instanceof CustomException) {
// 仅记录部分信息
Log::channel('slack')->warning('自定义异常发生:'.$e->getMessage());
return;
}
parent::report($e);
}
通过 render 方法,你可以自定义异常对应的 HTTP 响应。
public function render($request, Throwable $e)
{
if ($e instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $e);
}
Laravel 使用 Monolog 作为日志库。配置文件位于 config/logging.php。你可以定义多个“频道”,每个频道可以有不同的驱动和级别。
| 日志级别 | 说明 |
|---|---|
emergency | 系统不可用 |
alert | 需要立即采取行动 |
critical | 严重错误 |
error | 运行时错误 |
warning | 警告信息 |
notice | 普通但重要的事件 |
info | 一般信息 |
debug | 调试信息 |
.env 配置示例:
LOG_CHANNEL=stack
LOG_STACK=single,slack
LOG_LEVEL=debug
使用 Log Facade 可以轻松写入日志。你可以指定级别:
use Illuminate\Support\Facades\Log;
Log::emergency('系统崩溃');
Log::alert('数据库连接失败');
Log::critical('磁盘空间不足');
Log::error('用户认证失败', ['user_id' => 123]);
Log::warning('API 响应缓慢', ['time' => 5.2]);
Log::notice('任务已开始');
Log::info('用户登录成功', ['user' => 'admin']);
Log::debug('SQL 查询', ['sql' => 'select * from users']);
第二个参数可以传入关联数组,这些数据会被格式化为 JSON 附加到日志中。
Log::channel('slack')->info('系统通知', ['event' => 'deploy']);
你可以在 config/logging.php 中定义多个频道,并组合成“栈”(stack),同时写入多个位置。
'channels' => [
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'level' => 'error',
],
'stack' => [
'driver' => 'stack',
'channels' => ['single', 'slack'],
],
],
当发生 HTTP 异常(如 404、403、500)时,Laravel 会自动渲染对应的视图。你可以创建自定义视图文件:
resources/views/errors/404.blade.php – 404 页面resources/views/errors/403.blade.php – 禁止访问resources/views/errors/500.blade.php – 服务器错误resources/views/errors/419.blade.php – CSRF 过期示例 404 页面:
@extends('layouts.app')
@section('content')
<h1>404 - 页面未找到</h1>
<p>您访问的页面不存在。</p>
@endsection
在业务代码中,你可以手动抛出异常,Laravel 会自动处理并记录。
use App\Exceptions\CustomException;
if (!$user) {
throw new CustomException('用户不存在');
}
// 抛出 HTTP 异常
abort(403, '无权访问');
有些异常(如模型未找到)你不想记录到日志,可以在 Handler 的 $dontReport 属性中列出。
protected $dontReport = [
\Illuminate\Database\Eloquent\ModelNotFoundException::class,
\Symfony\Component\HttpKernel\Exception\HttpException::class,
];
APP_DEBUG=false,避免暴露敏感信息。daily 驱动,避免单个日志文件过大。
// 安装 sentry/sentry-laravel
// 在 Handler 的 report 方法中
public function report(Throwable $e)
{
if (app()->bound('sentry') && $this->shouldReport($e)) {
app('sentry')->captureException($e);
}
parent::report($e);
}
Artisan 命令失败时会输出错误信息到控制台;队列任务失败时,会记录到 failed_jobs 表。你可以自定义失败处理。
// 在任务类中定义 failed 方法
public function failed(Throwable $exception)
{
Log::error('队列任务失败', [
'job' => static::class,
'error' => $exception->getMessage(),
]);
}
Laravel 的异常处理和日志系统为你提供了完善的应用监控能力。通过自定义异常处理器、多频道日志和灵活的错误页面,你可以确保应用在出错时依然优雅,并能够快速定位问题根源。合理利用日志级别和上报工具,将大幅提升生产环境的可维护性。