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