设计思路
创建LogService类,执行LogService::addLog() 方法时,如果开始日志收集,将日志内容存入暂存,当前请求结束,执行LogService::send()统一发送日志.
实现方案
LogService类实现日志收集接口 :
class LogService implements LogServiceInterface
{
public static function addLog($module, $str)
{
//省略...
//是否开启日志栈
if (self::$beginTrack) {
self::push($module, $str);
} else {
self::addLog($module, $str);
}
}
}
/**
* 日志收集接口
*/
interface LogServiceInterface
{
/*开启日志收集 */
function beginTrack();
/**
* 结束收集
*/
function stopTrack();
/**
* 添加一条日志
*/
static function push($module, $str);
/**
* 预览日志
*/
static function review();
/**
* 发送日志并清空栈
*/
function send();
/**
* 清空所有日志
*/
function clear();
}
开启日志收集功能
LogService::beginTrack();
方案一: 借助YII权限验证接口,在controller出发afterAction事件时,写入日志
- 修改common\behaviors\AccessBehavior 文件如下:
public function events()
{
return [
Controller::EVENT_BEFORE_ACTION => 'beforeAction',
Controller::EVENT_AFTER_ACTION => 'afterAction', //添加afterAction事件
];
}
/**
* 控制器结束执行发送日志
*/
function afterAction(){
LogService::send();
}
方案二:监听YII的afterRequest事件
- 创建一个AppLogTarget类,
use yii\base\Component;
use yii\base\Event;
use yii\base\Application as BaseApp;
class AppLogTarget extends Component
{
function init()
{
Event::on(BaseApp::class,BaseApp::EVENT_AFTER_REQUEST,function(){
LogService::send();
});
}
}
- 修改配置文件 common/config/base.php,添加组件配置,并设置自动加载appLogTarget
'bootstrap' => ['log', 'queue','appLogTarget'],
'components' => [
'appLog'=>[
'class'=>\common\service\LogService::class
],
'appLogTarget'=>[
'class'=>\common\components\log\AppLogTarget::class
],
方案三:监听Response的 afterPrepare事件
- 在Web.php配置中增加afterPrepare配置
'response' => [
"format" => yii\web\Response::FORMAT_JSON,
'on afterPrepare' => function ($event) {
LogService::send();
}
],
总结一下
- Yii 的具体监听事件,要取决于所使用的对象。列出上述三个对象所具有的事件,
对象 | 事件 | 事件说明 |
---|---|---|
Application | beforeRequest | 请求进入业务之前 |
Application | afterRequest | 请求业务结束 |
Controller | beforeAction | 执行方法之前,执行构造函数之后 |
Controller | afterAction | 执行方法之后 |
Response | beforeSend | 响应之前,data为响应原始数据,content为null |
Response | afterPrepare | 处理响应数据之后,根据Content-Type格式化data,将值已存入content 中 |
Response | afterSend | 响应数据发送之后,已将content输出缓冲区 |
User | beforeLogin | 用户登录前 |
User | afterLogin | 用户登录之后 |
User | beforeLogout | 用户登出前 |
User | afterLogout | 用户登出之后 |
Model | beforeValidate | model验证参数前 |
Model | afterValidate | model验证参数后 |
- YII对象事件触发方式
$this->trigger(self::EVENT_BEFORE_ACTION,new Event());
- Yii添加监听事件的方式:
1))全局绑定事件
\yii\base\Event::on(Controller::className(), Controller::EVENT_BEFORE_ACTION, function ($event) {})
2)对象主动绑定行为
Yii::$app->controller->attachBehavior('access', [
'class' => $this->accessControlFilter,
]);
3)对象,定义behaviors函数绑定行为
function behaviors()
{
return [
GlobalAccessBehavior::class
];
}
4)行为类,定义events函数监听全局事件
class GlobalAccessBehavior extends Behavior
{
public function events()
{
return [
Controller::EVENT_BEFORE_ACTION => 'beforeAction'
];
}
public function beforeAction()
{
}
}