sentry适用于全链路错误监控与生产上报,phpbrake专注轻量上报,whoops仅限本地开发调试;三者不可混用,选错会导致功能缺失或安全风险。

直接用 composer require 装一个错误处理包(比如 sentry/sentry 或 php-brake/phpbrake),再在入口文件里初始化,就能让整个项目共享一套异常捕获逻辑——但前提是别漏掉自动加载、环境隔离和错误类型覆盖这三处关键环节。
怎么选包:Sentry、PHPBrake、Whoops 各自适用什么场景
选错包会导致功能冗余或关键链路失效:
-
whoops只适合本地开发:它把错误渲染成带堆栈的 HTML 页面,不能上报、不支持异步、生产环境启用等于暴露调试信息 -
sentry/sentry是全链路方案:支持 PHP 7.2+,能捕获Exception、Error(含TypeError、ValueError)、未捕获的致命错误(需配合register_shutdown_function),还自带采样、上下文附加、Release tracking -
php-brake/phpbrake更轻量:专注错误上报本身,不带 UI 和 SDK 管理,适合已用 Airbrake 或想最小侵入集成的项目
注意:PHP 8.5+ 的 EngineError(如 OOM)无法被 try/catch 捕获,必须靠 set_error_handler + register_shutdown_function 组合兜底,Sentry 默认已内置该逻辑,PHPBrake 需手动补。
全局初始化:别只写一次 require_once 'vendor/autoload.php'
入口文件(如 public/index.php)里初始化错误处理器是基础,但容易忽略两点:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 必须在
require_once 'vendor/autoload.php'之后立即注册,否则类找不到; - 若项目有多个入口(CLI 命令、队列 worker、WebSocket server),每个入口都得单独初始化,不能指望“一次配置全项目生效”;
- 环境判断要硬编码,别依赖
$_ENV或getenv()——它们可能被 CLI 的-d参数或 DockerENV覆盖,建议用file_exists(__DIR__.'/../.env.production')这类物理存在判断。
示例(Sentry):
require_once __DIR__ . '/../vendor/autoload.php';
if (file_exists(__DIR__ . '/../.env.production')) {
\Sentry\init(['dsn' => 'https://xxx@o123.ingest.sentry.io/456']);
}
自动加载陷阱:autoload-dev 会污染生产环境
很多错误处理包(如 symfony/var-dumper)被列为 require-dev,但 Sentry 的 Tracing 功能依赖它。如果只跑 composer install --no-dev,就会在调用 \Sentry\configureScope() 时抛出 Class not found。
- 解决方案不是去掉
--no-dev,而是把 Sentry 相关依赖明确移到require,哪怕它带了 dev-only 的工具类; - 检查
composer.json中是否误将sentry/sentry放在require-dev下——它不是开发工具,是运行时组件; - 执行
composer dump-autoload --optimize后,用composer show -p sentry/sentry确认类路径是否已纳入主 autoload map。
错误类型覆盖:PHP 8.5+ 的 Error 子类必须显式监听
PHP 8.5 引入更严格的错误分类,ValueError、TypeError、ArgumentCountError 全部继承自 Error,而传统 catch (\Exception $e) 不会捕获它们。
- 必须补一层
catch (\Error $e),且顺序要在Exception之后(否则会被提前截获); - Sentry 默认已注册
set_exception_handler和set_error_handler,但如果你自己写了set_exception_handler,就得手动把Error实例传给 Sentry 的captureException(); - 致命错误(如
Fatal error: Allowed memory size exhausted)只能靠register_shutdown_function检查error_get_last(),这个逻辑 Sentry 内置了,但需确认enable_tracing关闭时它仍启用。
真正难搞的是跨进程场景:CLI 命令里触发的 EngineError(OOM)不会被 Web 入口的 Sentry 初始化捕获——每个进程必须独立初始化。










