yii\base\Controller 處理路由解析、動作建立、參數綁定、前後置鉤子、視圖渲染與佈局查找。本文節選關鍵方法原始碼並解析核心邏輯。
run($route, $params)public function run($route, $params = []) {
$pos = strpos($route, '/');
if ($pos === false) return $this->runAction($route, $params); // 當前控制器動作
elseif ($pos > 0) return $this->module->runAction($route, $params); // 子模組路由
else return Yii::$app->runAction(ltrim($route, '/'), $params); // 絕對路由(從應用根)
}
createAction($id)public function createAction($id) {
if ($id === '') $id = $this->defaultAction;
$actionMap = $this->actions(); // 覆寫 actions() 回傳獨立 Action 類別配置
if (isset($actionMap[$id])) return Yii::createObject($actionMap[$id], [$id, $this]);
// 行為動作:actionXyz 對應方法 actionXyz
if (preg_match('/^[a-z0-9\\-_]+$/', $id) && strpos($id, '--') === false && trim($id, '-') === $id) {
$methodName = 'action' . str_replace(' ', '', ucwords(implode(' ', explode('-', $id))));
if (method_exists($this, $methodName)) {
$method = new \ReflectionMethod($this, $methodName);
if ($method->isPublic() && $method->getName() === $methodName)
return new InlineAction($id, $this, $methodName);
}
}
return null;
}
支援獨立 Action 類別與行為動作(方法名)雙模式,命名規則:action-id → actionActionId。
public function beforeAction($action) {
$event = new ActionEvent($action);
$this->trigger(self::EVENT_BEFORE_ACTION, $event);
return $event->isValid; // false 可中斷執行
}
public function afterAction($action, $result) {
$event = new ActionEvent($action);
$event->result = $result;
$this->trigger(self::EVENT_AFTER_ACTION, $event);
return $event->result;
}
render() / renderContent() / renderPartial() / renderFile()public function render($view, $params = []) {
$content = $this->getView()->render($view, $params, $this); // 渲染視圖檔
return $this->renderContent($content); // 套用佈局
}
public function renderContent($content) {
$layoutFile = $this->findLayoutFile($this->getView());
return $layoutFile !== false
? $this->getView()->renderFile($layoutFile, ['content' => $content], $this)
: $content;
}
public function renderPartial($view, $params = []) {
return $this->getView()->render($view, $params, $this); // 不套用佈局
}
public function renderFile($file, $params = []) {
return $this->getView()->renderFile($file, $params, $this);
}
findLayoutFile($view)$this->layout 為字串 → 直接使用。null → 向上遞歸查找父模組 layout 非空者。@alias → Yii::getAlias()/path → 應用 layoutPathrelative → 當前模組 layoutPathview->defaultExtension,回退 .php。public function getView() {
return $this->_view ?? ($this->_view = Yii::$app->getView());
}
getModules() / getUniqueId() / getRoute()public function getModules() {
$modules = [$this->module];
$module = $this->module;
while ($module->module !== null) {
array_unshift($modules, $module->module);
$module = $module->module;
}
return $modules;
}
public function getUniqueId() {
return $this->module instanceof Application ? $this->id : $this->module->getUniqueId() . '/' . $this->id;
}
public function getRoute() {
return $this->action ? $this->action->getUniqueId() : $this->getUniqueId();
}
Controller 基類將「路由→動作建立→參數綁定→前置鉤子→執行→後置鉤子→視圖渲染→佈局套用」完整串聯,並提供靈活的覆寫點(actions()、beforeAction()、findLayoutFile()),是 Yii2 請求處理管線的核心樞紐。