我對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
1 >>> $arr = ['a' => 2, 'b' => 3]; 2 => [ 3 "a" => 2, 4 "b" => 3, 5 ] 6 >>> extract($arr); 7 => 2 8 >>> $a 9 => 2 10 >>> $b 11 => 3
那么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,視圖渲染過程的簡單分析
這個。。。時間有點兒晚了,有時間再說。
參考資料:
完