
Yii 1.1 中 Yii::log() 调用看似执行成功但日志未落盘,通常并非配置或语法问题,而是由脚本异常中断(如超时、无限循环、未捕获异常)导致日志缓冲未刷新,或存在隐式终止流程(如 exit、die、致命错误)使 CLogRouter 的 processLogs() 未能触发。
yii 1.1 中 `yii::log()` 调用看似执行成功但日志未落盘,通常并非配置或语法问题,而是由脚本异常中断(如超时、无限循环、未捕获异常)导致日志缓冲未刷新,或存在隐式终止流程(如 `exit`、`die`、致命错误)使 `clogrouter` 的 `processlogs()` 未能触发。
在 Yii 1.1 中,日志并非实时写入文件,而是采用缓冲 + 请求结束时批量处理机制:所有 Yii::log() 调用仅将日志消息暂存至内存队列;真正的写入操作由 CLogRouter 在应用生命周期末期(即 Yii::app()->end() 或脚本自然结束前)统一调用 processLogs() 完成。这意味着:只要脚本未正常结束,日志就永远不会落地。
你遇到的现象——仅首条日志(Entered foo())可见,后续日志全部丢失,但数据库更新却成功发生——正是该机制的典型表现。结合你的补充说明(新增 else 分支后出现 foo(): thing is null,但数据库仍被修改),可明确推断:
✅ foo() 和 bar() 确实被执行;
✅ 数据库变更发生在日志应写入之前;
❌ 但脚本在后续某处非正常终止(如超时、递归死循环、fatal error),导致 processLogs() 永远未被调用。
你最终定位到的「274,000 行递归查询引发的近似无限循环」正是关键原因:它消耗完 PHP 执行时间(max_execution_time),触发脚本强制终止(如 Fatal error: Maximum execution time of X seconds exceeded),此时 Yii 的日志处理器已无机会运行。
✅ 正确排查与解决步骤
-
确认日志组件已启用且配置正确(排除基础配置问题)
检查protected/config/main.php中log路由器是否启用:'components' => [ 'log' => [ 'class' => 'CLogRouter', 'routes' => [ [ 'class' => 'CFileLogRoute', 'levels' => 'error, warning, info, trace, dev', // 确保包含 'dev' 'categories' => 'My.Code.Example', 'logFile' => 'application.log', ], ], ], ], -
强制刷新日志缓冲(调试阶段)
在关键位置手动触发日志写入,验证是否为“未结束”问题:Yii::log('foo(): thing is not null', 'dev', 'My.Code.Example'); Yii::app()->log->route('file')->processLogs(); // 强制立即写入(仅调试用) -
捕获并记录致命错误
在入口文件(如index.php)顶部添加错误处理,防止静默崩溃:register_shutdown_function(function() { $error = error_get_last(); if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { Yii::log("FATAL ERROR: {$error['message']} in {$error['file']}:{$error['line']}", 'error', 'System'); // 同时写入系统日志确保可见 error_log("[YII-FATAL] {$error['message']} | {$error['file']}:{$error['line']}"); } }); -
优化高负载逻辑,避免超时
针对你的递归大数据查询,改用分页、迭代或异步任务:// ❌ 危险:一次性加载全部 $models = Model::model()->findAll(); // ✅ 安全:分批处理 $offset = 0; $limit = 1000; do { $batch = Model::model()->findAll([ 'limit' => $limit, 'offset' => $offset, ]); foreach ($batch as $model) { // 处理单条 Yii::log("Processing #{$model->id}", 'dev', 'Batch'); } $offset += count($batch); } while (count($batch) === $limit);
⚠️ 重要注意事项
-
Yii::log()是轻量级调用,不保证立即持久化;生产环境切勿依赖其作为关键操作的唯一追踪手段。 - 开启
display_errors = Off且log_errors = On的 PHP 配置,确保底层错误也被记录。 - 使用
tail -f runtime/logs/application.log实时监控日志,配合strace -e trace=write php index.php可辅助验证系统调用是否发出。
通过理解 Yii 1.1 日志的生命周期,并主动防御性地处理脚本终止场景,即可彻底解决“日志丢失但业务生效”的疑难问题。


















