Bugsnag 无官方 CodeIgniter SDK,需手动集成:CI3 要重写 MY_Exceptions 类覆盖 show_exception() 和 show_php_error() 并提前配置;CI4 则通过中间件注入,注意禁用 Whoops、调整注册顺序,并补充请求与用户上下文。

Bugsnag 本身没有官方维护的 CodeIgniter 专用 SDK,但你可以通过 Composer 引入通用 PHP SDK,并手动集成到 CodeIgniter(尤其是 CI3)中实现错误上报。关键不是“能不能用”,而是“怎么绕过框架默认错误处理、确保异常不被吞掉”。
为什么直接 require bugsnag/bugsnag 会失效
CodeIgniter 3 的错误处理链路是:PHP 错误 → set_error_handler() → CI 自己的 _error_handler() → show_error() 或写日志 → 静默退出。这意味着未捕获异常根本不会走到 Bugsnag::notifyException() 这一步。
- CI3 默认把所有错误转成
show_error()页面并调用exit(),Bugsnag的自动监听器(如register_shutdown_function)来不及触发 -
Bugsnag::registerCallback()必须在异常抛出前就注册好,而 CI 的Exceptions类在报错时才初始化 - 如果你在控制器里手动
Bugsnag::notifyException($e),没问题;但框架级崩溃(如路由找不到、数据库连接失败、类加载失败)你根本抓不到对象
必须重写 CI3 的 Exceptions 类
最可靠的方式是替换掉 system/core/Exceptions.php —— 但更安全的做法是继承它,在 application/core/MY_Exceptions.php 中覆盖关键方法:
- 重写
show_exception():在调用父方法前,先执行Bugsnag::notifyException($exception) - 重写
show_php_error():对E_ERROR、E_PARSE等致命错误,用Bugsnag::notifyError()手动上报(注意:这类错误无法 throw Exception,只能传 message + code) - 确保
Bugsnag::configure()在MY_Exceptions构造函数或__construct()中完成,且 API key 来自环境变量或配置文件,不要硬编码
示例片段(application/core/MY_Exceptions.php):
class MY_Exceptions extends CI_Exceptions
{
public function __construct()
{
parent::__construct();
// 初始化 Bugsnag(需提前 require vendor/autoload.php)
\Bugsnag\Bugsnag::configure([
'apiKey' => getenv('BUGSNAG_API_KEY') ?: config_item('bugsnag_api_key'),
]);
}
public function show_exception($exception)
{
\Bugsnag\Bugsnag::notifyException($exception);
parent::show_exception($exception);
}
public function show_php_error($severity, $message, $filepath, $line)
{
if (in_array($severity, [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
\Bugsnag\Bugsnag::notifyError($message, $severity, [
'file' => $filepath,
'line' => $line
]);
}
parent::show_php_error($severity, $message, $filepath, $line);
}
}
CI4 的集成更简单但仍有陷阱
CodeIgniter 4 使用 PSR-15 中间件和现代异常处理机制,Bugsnag 可以通过中间件注入,但要注意两点:
- CI4 默认启用
Whoops错误页面(开发环境),它会拦截异常并渲染 HTML,导致Bugsnag收不到 —— 必须在app/Config/Exceptions.php中禁用:public bool $log = true;且public bool $show = false;(生产环境) - 中间件注册顺序很重要:你的 Bugsnag 中间件必须放在最外层(
app/Config/Toolbar.php或app/Config/Filters.php中靠前),否则被其他中间件提前return就失效了 - CI4 的
Services::exceptions()是单例,可直接在中间件中调用$this->exceptions->log()后再发给 Bugsnag,避免重复上报
别忽略 HTTP 上下文和用户标识
单纯上报异常堆栈没用,Bugsnag 的价值在于关联请求现场。CI3 没有统一的 request 对象,你需要手动提取:
- 在
MY_Exceptions::show_exception()中,用$_SERVER['REQUEST_URI']、$_SERVER['REQUEST_METHOD']、$this->input->ip_address()(需加载 Input 类)补全 metadata - 用户信息不能依赖 session(可能已销毁),优先用
$this->session->has_userdata('user_id')安全判断后再附加 - CI4 可直接用
service('request')和service('session'),但注意:异常发生在中间件链早期时,session 可能尚未启动,要加try/catch包裹
真正容易被忽略的是:CI 的 show_404() 不抛异常,它只是输出页面并 exit —— 这类“业务错误”不会进 Bugsnag,必须在路由或控制器里主动 Bugsnag::leaveBreadcrumb('404 on '.$uri) 或 notifyException(new RuntimeException("404: $uri"))。


















