摘要:行處理視圖文件名后綴。結語從源碼上看,使用了原始作為模版機制使得視圖邏輯非常簡單。無非也就是把視圖進來,用輸出緩沖把執行結果拿到即可。此文可以轉載,但轉載前需要發郵件到進行溝通,未溝通的均視作侵權。
前言
CI 的 View 沒有像 Laravel 等一些流行框架一樣設計的那么重,有自己的一套模版機制,CI 一直采用純天然的 PHP 模板形式,純天然的好處是不用再學習一套模板語言了,缺點是不能用到一些便利的設計模式,比如不能使用繼承布局等等,當然你也可以加第三方的視圖組件進來。
下面我們開始看源碼,看源碼,我們先從視圖的調用開始。
視圖的調用CI 4 開始使用新的視圖調用邏輯,不在是 load 形式,調用方式如下:
echo view("name");
可以看到是直接調用了一個 view 函數,這個函數我們既不需要提前 load , 在 construct 方法里也沒看見 include 什么文件,同時,這個方法看起來又不屬于控制器對象,那么它是從哪里來的呢?
回到之前寫的“之二——入口以及初始化操作”一節,里面提到了,在 bootstrap.php 74 行(原始文件行號), require 了一下 BASEPATH."Common.php" ,這個文件中定義了許多輔助方法。 view 就是其中一個,該方法位于 system/common.php 中的 88 行(原始文件行號)。下面把代碼貼出來:
if (! function_exists("view")) { function view(string $name, array $data = [], array $options = []) { $renderer = Services::renderer(); $saveData = null; if (array_key_exists("saveData", $options) && $options["saveData"] === true) { $saveData = (bool)$options["saveData"]; unset($options["saveData"]); } return $renderer->setData($data, "raw") ->render($name, $options, $saveData); } }
可以看到,這里調用了 Services 類的 renderer 靜態方法。之后的 saveData 邏輯主要處理多次調用 view 方法時是否共享視圖變量以及最后把要傳遞給視圖的數據變量通過 $renderer->setData 方法傳遞給 render ,最后又執行了 render 進行渲染視圖。下面貼出的是 Services::renderer() 源碼(system/config/services.php:362):
public static function renderer($viewPath = APPPATH."Views/", $config = null, $getShared = true) { if ($getShared) { return self::getSharedInstance("renderer", $viewPath, $config); } if (is_null($config)) { $config = new ConfigView(); } return new CodeIgniterViewView($config, $viewPath, self::locator(true), CI_DEBUG, self::logger(true)); }
可以看出, view 方法主要 new 了一個 CodeIgniterViewView 類,該類位于 /system/ViewView.php 下。
小結一下,給個分析過程圖,以方便理解:
接下來就是我們的主角 View 了。
View 源碼分析按著以上圖中流程,我們要看 View 類的三個關鍵方法,分別是 __construct 、 setData 、 render 。
public function __construct($config, string $viewPath = null, $loader = null, bool $debug = null, Logger $logger = null) { $this->config = $config; $this->viewPath = rtrim($viewPath, "/ ")."/"; $this->loader = is_null($loader) ? Services::locator() : $loader; $this->logger = is_null($logger) ? Services::logger() : $logger; $this->debug = is_null($debug) ? CI_DEBUG : $debug; $this->saveData = $config->saveData ?? null; }
可以看到在 services new 的時候,僅僅傳遞了配置信息以及視圖路徑,視圖數據不在初始化之列。
public function setData(array $data=[], string $context=null): RendererInterface { if ( ! empty($context)) { $data = esc($data, $context); } $this->data = array_merge($this->data, $data); return $this; }
此方法主要用途是往視圖里壓數據,實際上就是把新壓的數據和對象中原有的數據(數據)合并一下。
作為視圖邏輯,渲染視圖肯定是一個重中之重的過程。
以下是去掉注釋和空行的源碼截圖(源碼分析中涉及到的行號是截圖中的行號):
142 行:由參數可以看出,調用 render 方法時才把具體的視圖文件名傳遞進來,因視圖數據通過 setData 方法放到了當前對象的 data 屬性里,因此無需再次傳遞。
145-147,170-172 行,處理是否將本次壓進來的視圖數據共享給下次 render 過程。這個 $saveData 可以在 application/config/view.php 里配置,默認是 false 。
149 行:處理視圖文件名后綴。
150-158 行,判斷開始緩存設置的話,處理視圖緩存。
159-168 行,嘗試著通過自動加載機制找到視圖文件。找不到,拋異常。
168 行,很重要(劃重點),該方法是將壓進來的數組形式的數據擴展開成 $key=$value 形式,因為視圖是 include 進來的普通 php 因此,在視圖中也就可以用 $key 的形式讀取到變量的內容。
174-177 行,開啟輸出控制緩沖機制,并 include 進來視圖,相當于同時執行了這個文件,這個文件中的普通 html 亦或是執行 php 后的輸出,都會被輸出緩沖接收到并賦值給了 $output 。
179-182 行,前邊的緩存是處理讀取過程,這里是處理寫入過程。
183 行,最后返回渲染結果。
結語從源碼上看, CI 使用了原始 PHP 作為模版機制使得視圖邏輯非常簡單。無非也就是把視圖 include 進來,用輸出緩沖把執行結果拿到即可。
此文可以轉載,但轉載前需要發郵件到imustgxd*sina.cn進行溝通,未溝通的均視作侵權。 轉載同時需注明鏈接,并保留此段文字。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22978.html
摘要:行,是否強制訪問。行,嘗試處理此次請求,詳細見方法。至此,的執行主流程完畢。小結是的核心文件,它被調用后,完成了諸多的主流程操作。此文可以轉載,但轉載前需要發郵件到進行溝通,未溝通的均視作侵權。 前言 Codeigniter.php 是 CI 4 的核心所在,在這里接收并處理了 request 請求,安全檢查,緩存處理, URL 解析以及路由匹配,執行過濾器,加載運行 Controll...
摘要:控制器嚴格來說,這個是控制器父類的源碼。在中,控制器僅負責接到返回的組裝的頁面字符串,并回核心中,由核心再處理后續事宜。此文可以轉載,但轉載前需要發郵件到進行溝通,未溝通的均視作侵權。 前言 其實一開始我是很糾結是否要寫控制器的源碼分析的,因為控制器的源碼太少了,少到你不相信這是一個 MVC 里的一個重頭。直覺里,大家都覺得控制器作為各個請求的入口,其后端應該有很多很多的代碼支撐才可以...
摘要:支持命名空間是沒有支持命名空間的。配置文件不再是簡單數組了新的配置文件是以對象組織的,各個配置以對象的屬性形式暴露出來。此文可以轉載,但轉載前需要發郵件到進行溝通,未溝通的均視作侵權。 前言 CI 為了追上大家的腳步,這次跨了一大步,盡量使用了更多的流行設計理念,甚至連 PHP 的支持版本都是從 7 開始起步的。我在之前閱讀源碼的同時也發現了很多變化的地方,在此把已經發現的列舉出來,不...
摘要:版權聲明可轉載,但不論任何媒體都需要在轉載前與本人溝通,并在轉載時注明出處。的各個核心模塊以模塊名為目錄名分別存儲在這個目錄下。下一篇文章會涉及到和。此文可以轉載,但轉載前需要發郵件到進行溝通,未溝通的均視作侵權。 寫在前面: 為什么選擇開發過程中的 CI 4 作為源碼解讀版本:(1)首先我選 CI 是因為它之前的穩定版都是相對比較輕量小巧的,而且可以認為是簡單的。(2)為什么沒有選...
摘要:通過這個函數可以很方便的在程序運行期間執行很多常見操作。此文可以轉載,但轉載前需要發郵件到進行溝通,未溝通的均視作侵權。 index.php index.php 是整個框架的入口文件,也就是說所有的請求都要從它這里開始。因為 index.php 源碼非常簡潔,那么我們直接放一張源碼截圖,按著截圖說一下源碼。 showImg(https://segmentfault.com/img/re...
閱讀 4152·2023-04-26 02:40
閱讀 2655·2023-04-26 02:31
閱讀 2746·2021-11-15 18:08
閱讀 568·2021-11-12 10:36
閱讀 1425·2021-09-30 09:57
閱讀 5192·2021-09-22 15:31
閱讀 2626·2019-08-30 14:17
閱讀 1269·2019-08-30 12:58