基于 robmcvey 的解决方案,这是我必须为 CakePHP 2.6 做的事情。
配置
在app/Config/core.php更新异常配置:
Configure::write('Exception', array(
'handler' => 'AppErrorHandler::handleException',
'renderer' => 'ExceptionRenderer',
'log' => true
));
在app/Config/bootstrap.php 中添加一个 CakeLog 配置:
CakeLog::config('not_found', array(
'engine' => 'FileLog',
'types' => array('404'),
'file' => '404',
));
404 的 type 是日志级别,它将监听写入日志的任何内容,例如CakeLog::write('404', 'That was not found.');
扩展错误处理程序
创建文件app/Lib/Error/AppErrorHandler.php。这里我们将扩展Cake的ErrorHandler,覆盖三个方法; handleException()、_getMessage() 和 _log()。
<?php
class AppErrorHandler extends ErrorHandler {
/**
* List of Cake Exception classes to record to specified log level.
*
* @var array
*/
protected static $_exceptionClasses = array(
'MissingControllerException' => '404',
'MissingActionException' => '404',
'PrivateActionException' => '404',
'NotFoundException' => '404'
);
public static function handleException(Exception $exception) {
$config = Configure::read('Exception');
self::_log($exception, $config);
$renderer = isset($config['renderer']) ? $config['renderer'] : 'ExceptionRenderer';
if ($renderer !== 'ExceptionRenderer') {
list($plugin, $renderer) = pluginSplit($renderer, true);
App::uses($renderer, $plugin . 'Error');
}
try {
$error = new $renderer($exception);
$error->render();
} catch (Exception $e) {
set_error_handler(Configure::read('Error.handler')); // Should be using configured ErrorHandler
Configure::write('Error.trace', false); // trace is useless here since it's internal
$message = sprintf("[%s] %s\n%s", // Keeping same message format
get_class($e),
$e->getMessage(),
$e->getTraceAsString()
);
self::$_bailExceptionRendering = true;
trigger_error($message, E_USER_ERROR);
}
}
/**
* Generates a formatted error message
*
* @param Exception $exception Exception instance
* @return string Formatted message
*/
protected static function _getMessage($exception) {
$message = '';
if (php_sapi_name() !== 'cli') {
$request = Router::getRequest();
if ($request) {
$message .= $request->here() . " Not Found";
}
}
$message .= "\nStack Trace:\n" . $exception->getTraceAsString() . "\n";
return $message;
}
/**
* Handles exception logging
*
* @param Exception $exception The exception to render.
* @param array $config An array of configuration for logging.
* @return bool
*/
protected static function _log(Exception $exception, $config) {
if (!empty(self::$_exceptionClasses)) {
foreach ((array)self::$_exceptionClasses as $class => $level) {
if ($exception instanceof $class) {
return CakeLog::write($level, self::_getMessage($exception));
}
}
}
return parent::_log();
}
}
您可以自定义$_exceptionClasses 数组以捕获您想要的异常并将它们发送到不同的日志。 _getMessage() 方法已被简化以删除属性。
结果
/exploitable-plugin 等随机 URL 现在将登录到 tmp/logs/404.log。
2015-04-01 16:37:54 404: /exploitable-plugin Not Found
Stack Trace:
#0 /var/example.com/app/index.php(146): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
#1 {main}