菜鸟常忽略的基础 - 获取当前请求的控制器和方法

  • 作者:KK

  • 发表日期:2016.9.8


要点速读

一般在控制器里、模板、模型、你调用的各种类里面用下面的代码就能获取当前的控制器ID和方法ID:

print_r([
	Yii::$app->controller->id,
	Yii::$app->controller->action->id,
]);

有时候偏偏就是访问不到引发报错

但玩得多的朋友应该会发觉,并非每次都能访问得到,有时候偏偏就是得不到,可是拼写也没错呀

请先看yii\base\Module::runAction的源代码:

如果刚开始运行,那么Yii::$app->controller是null,于是$oldController取到的值就是null

yii\base\Controller::runAction完成以后又将$oldController放了回去,于是Yii::$app->controller又变成了null

所以如果不是在模块里,则在框架运行yii\base\Module::runAction之前,包括yii\base\Module::createController的时候访问Yii::$app->controller都会得到null,于是更甭想得到action了


而在yii\base\Controller::runAction后controller又成了null,于是在这之后的流程都会得不到Yii::$app->controller

重点是这些后面的流程都有哪些呢?我主要以Web应用为例子讲解一下,希望你在这些地方用的时候要清楚controller无法访问到:

  1. 发送响应数据(yii\web\Response::send

    调用yii\base\Module::runAction的就是yii\web\Application::handleRequest

    这个handleRequest方法runAction后没什么流程调用,就是整理了一下Response再返回给外面,我们再追踪到外面

    那就是我们在入口文件调用的yii\base\Application::run方法,它里面执行了$response->send()

    以及$response->send之前触发的yii\base\Application::EVENT_AFTER_REQUEST事件

  2. 程序终止处理环节

    yii\base\ErrorHander::register里用register_shutdown_function注册过程序终止回调,所以在程序终止处理里面的一堆事情也访问不到Yii::$app->controller

    程序终止的处理代码在yii\base\ErrorHander::handleFatalError,里面主要的事情有:

    1. 记录异常日志($this->logException($exception)触发)

    2. 消息调度(Yii::getLogger()->flush(true)触发,再到yii\log\Logger::flush调用$this->dispatcher->dispatch($messages, $final)

      这样的话一切log组件里的自定义yii\log\Target的处理代码都访问不到Yii::$app->controller