我對yii2的控制器中的變數如何渲染到視圖中這個問題一直很好奇, 另外, 我還對yii2如何載入靜態資源, 如js和css比較好奇, 於是趁著週末就看了下yii2的相關源碼想把這兩個問題都弄明白。 變數如何渲染到視圖中是弄明白了, 但是靜態資源的載入問題還是沒有弄明白, 做人不難太貪心, 先把這個弄明白了, 後續再說另一個。
1, 先把yii2中相關的關鍵代碼貼出來看下
yii\web\View繼承了yii\base\View
yii2的yii\base\View中的幾個關鍵方法:
public function render($view, $params = [], $context = null) { $viewFile = $this->findViewFile($view, $context); return $this->renderFile($viewFile, $params, $context); } public function renderFile($viewFile, $params = [], $context = null) { $viewFile = Yii::getAlias($viewFile); if ($this->theme !== null) { $viewFile = $this->theme->applyTo($viewFile); } if (is_file($viewFile)) { $viewFile = FileHelper::localize($viewFile); } else { throw new ViewNotFoundException("The view file does not exist: $viewFile"); } $oldContext = $this->context; if ($context !== null) { $this->context = $context; } $output = ''; $this->_viewFiles = $viewFile; if ($this->beforeRender($viewFile, $params)) { Yii::trace("Rendering view file: $viewFile", __METHOD__); $ext = pathinfo($viewFile, PATHINFO_EXTENSION); if (isset($this->renderers[$ext])) { if (is_array($this->renderers[$ext]) || is_string($this->renderers[$ext])) { $this->renderers[$ext] = Yii::createObject($this->renderers[$ext]); } /* @var $renderer ViewRenderer */ $renderer = $this->renderers[$ext]; $output = $renderer->render($this, $viewFile, $params); } else { $output = $this->renderPhpFile($viewFile, $params); } $this->afterRender($viewFile, $params, $output); } array_pop($this->_viewFiles); $this->context = $oldContext; return $output; } public function renderPhpFile($_file_, $_params_ = []) { ob_start; ob_implicit_flush(false); extract($_params_, EXTR_OVERWRITE); require($_file_); return ob_get_clean; }我現在這個水準只是對代碼(功能)的實現比較好奇, 其實yii2框架代碼的組織、框架設計都很值得學習, 不過這都是後話,
功能實現的關鍵就在renderPhpFile($_file_, $_params_ = [])這個方法裡, 而這個方法的關鍵又是:extract($_params, EXTR_OVERWRITE);, 這個php函數的神奇之處在於, 它可以將關聯陣列導入到一個變數表中, 就是將陣列鍵作為變數名、值作為變數的值進行賦值。 比如下面這個簡單的例子:
Psy Shell v0.7.2 (PHP 5.6.29 — cli) by Justin Hileman那麼yii2視圖中的變數值是怎麼傳遞過來的也就很好理解了。
2, 變數注入過程的簡單分析
ob_start打開輸出緩衝區, 這樣php腳本中要輸出的內容, 比如變數值等, 就不會輸出到輸出設備(如螢幕), 而是存儲到php自身的一個緩衝區中, 在這些內容被沖刷出緩衝區之前, 我們可以對這些內容進行操作, 比如格式化下等。
ob_implicit_flush(false)關閉內部的絕對(隱式)刷送, 它的效果其實等同於調用flush只不過如果打開它那就不用再主動調用flush了,
extract($_params, EXTR_OVERWRITE);將控制器變數陣列鍵值注入到對應的鍵名變數清單。
require($_file);載入視圖檔
return ob_get_clean; ob_get_clean獲取當前緩衝區內容, 關閉(刪除)當前的輸出緩衝區。
3, 視圖渲染過程的簡單分析
這個。 。 。 時間有點兒晚了, 有時間再說。
參考資料:
php手冊
yii2
完