摘要:行處理視圖文件名后綴。結(jié)語(yǔ)從源碼上看,使用了原始作為模版機(jī)制使得視圖邏輯非常簡(jiǎn)單。無(wú)非也就是把視圖進(jìn)來(lái),用輸出緩沖把執(zhí)行結(jié)果拿到即可。此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到進(jìn)行溝通,未溝通的均視作侵權(quán)。
前言
CI 的 View 沒有像 Laravel 等一些流行框架一樣設(shè)計(jì)的那么重,有自己的一套模版機(jī)制,CI 一直采用純天然的 PHP 模板形式,純天然的好處是不用再學(xué)習(xí)一套模板語(yǔ)言了,缺點(diǎn)是不能用到一些便利的設(shè)計(jì)模式,比如不能使用繼承布局等等,當(dāng)然你也可以加第三方的視圖組件進(jìn)來(lái)。
下面我們開始看源碼,看源碼,我們先從視圖的調(diào)用開始。
視圖的調(diào)用CI 4 開始使用新的視圖調(diào)用邏輯,不在是 load 形式,調(diào)用方式如下:
echo view("name");
可以看到是直接調(diào)用了一個(gè) view 函數(shù),這個(gè)函數(shù)我們既不需要提前 load , 在 construct 方法里也沒看見 include 什么文件,同時(shí),這個(gè)方法看起來(lái)又不屬于控制器對(duì)象,那么它是從哪里來(lái)的呢?
回到之前寫的“之二——入口以及初始化操作”一節(jié),里面提到了,在 bootstrap.php 74 行(原始文件行號(hào)), require 了一下 BASEPATH."Common.php" ,這個(gè)文件中定義了許多輔助方法。 view 就是其中一個(gè),該方法位于 system/common.php 中的 88 行(原始文件行號(hào))。下面把代碼貼出來(lái):
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); } }
可以看到,這里調(diào)用了 Services 類的 renderer 靜態(tài)方法。之后的 saveData 邏輯主要處理多次調(diào)用 view 方法時(shí)是否共享視圖變量以及最后把要傳遞給視圖的數(shù)據(jù)變量通過(guò) $renderer->setData 方法傳遞給 render ,最后又執(zhí)行了 render 進(jìn)行渲染視圖。下面貼出的是 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 了一個(gè) CodeIgniterViewView 類,該類位于 /system/ViewView.php 下。
小結(jié)一下,給個(gè)分析過(guò)程圖,以方便理解:
接下來(lái)就是我們的主角 View 了。
View 源碼分析按著以上圖中流程,我們要看 View 類的三個(gè)關(guān)鍵方法,分別是 __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 的時(shí)候,僅僅傳遞了配置信息以及視圖路徑,視圖數(shù)據(jù)不在初始化之列。
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; }
此方法主要用途是往視圖里壓數(shù)據(jù),實(shí)際上就是把新壓的數(shù)據(jù)和對(duì)象中原有的數(shù)據(jù)(數(shù)據(jù))合并一下。
作為視圖邏輯,渲染視圖肯定是一個(gè)重中之重的過(guò)程。
以下是去掉注釋和空行的源碼截圖(源碼分析中涉及到的行號(hào)是截圖中的行號(hào)):
142 行:由參數(shù)可以看出,調(diào)用 render 方法時(shí)才把具體的視圖文件名傳遞進(jìn)來(lái),因視圖數(shù)據(jù)通過(guò) setData 方法放到了當(dāng)前對(duì)象的 data 屬性里,因此無(wú)需再次傳遞。
145-147,170-172 行,處理是否將本次壓進(jìn)來(lái)的視圖數(shù)據(jù)共享給下次 render 過(guò)程。這個(gè) $saveData 可以在 application/config/view.php 里配置,默認(rèn)是 false 。
149 行:處理視圖文件名后綴。
150-158 行,判斷開始緩存設(shè)置的話,處理視圖緩存。
159-168 行,嘗試著通過(guò)自動(dòng)加載機(jī)制找到視圖文件。找不到,拋異常。
168 行,很重要(劃重點(diǎn)),該方法是將壓進(jìn)來(lái)的數(shù)組形式的數(shù)據(jù)擴(kuò)展開成 $key=$value 形式,因?yàn)橐晥D是 include 進(jìn)來(lái)的普通 php 因此,在視圖中也就可以用 $key 的形式讀取到變量的內(nèi)容。
174-177 行,開啟輸出控制緩沖機(jī)制,并 include 進(jìn)來(lái)視圖,相當(dāng)于同時(shí)執(zhí)行了這個(gè)文件,這個(gè)文件中的普通 html 亦或是執(zhí)行 php 后的輸出,都會(huì)被輸出緩沖接收到并賦值給了 $output 。
179-182 行,前邊的緩存是處理讀取過(guò)程,這里是處理寫入過(guò)程。
183 行,最后返回渲染結(jié)果。
結(jié)語(yǔ)從源碼上看, CI 使用了原始 PHP 作為模版機(jī)制使得視圖邏輯非常簡(jiǎn)單。無(wú)非也就是把視圖 include 進(jìn)來(lái),用輸出緩沖把執(zhí)行結(jié)果拿到即可。
此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到imustgxd*sina.cn進(jìn)行溝通,未溝通的均視作侵權(quán)。 轉(zhuǎn)載同時(shí)需注明鏈接,并保留此段文字。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/22978.html
摘要:行,是否強(qiáng)制訪問(wèn)。行,嘗試處理此次請(qǐng)求,詳細(xì)見方法。至此,的執(zhí)行主流程完畢。小結(jié)是的核心文件,它被調(diào)用后,完成了諸多的主流程操作。此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到進(jìn)行溝通,未溝通的均視作侵權(quán)。 前言 Codeigniter.php 是 CI 4 的核心所在,在這里接收并處理了 request 請(qǐng)求,安全檢查,緩存處理, URL 解析以及路由匹配,執(zhí)行過(guò)濾器,加載運(yùn)行 Controll...
摘要:控制器嚴(yán)格來(lái)說(shuō),這個(gè)是控制器父類的源碼。在中,控制器僅負(fù)責(zé)接到返回的組裝的頁(yè)面字符串,并回核心中,由核心再處理后續(xù)事宜。此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到進(jìn)行溝通,未溝通的均視作侵權(quán)。 前言 其實(shí)一開始我是很糾結(jié)是否要寫控制器的源碼分析的,因?yàn)榭刂破鞯脑创a太少了,少到你不相信這是一個(gè) MVC 里的一個(gè)重頭。直覺里,大家都覺得控制器作為各個(gè)請(qǐng)求的入口,其后端應(yīng)該有很多很多的代碼支撐才可以...
摘要:支持命名空間是沒有支持命名空間的。配置文件不再是簡(jiǎn)單數(shù)組了新的配置文件是以對(duì)象組織的,各個(gè)配置以對(duì)象的屬性形式暴露出來(lái)。此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到進(jìn)行溝通,未溝通的均視作侵權(quán)。 前言 CI 為了追上大家的腳步,這次跨了一大步,盡量使用了更多的流行設(shè)計(jì)理念,甚至連 PHP 的支持版本都是從 7 開始起步的。我在之前閱讀源碼的同時(shí)也發(fā)現(xiàn)了很多變化的地方,在此把已經(jīng)發(fā)現(xiàn)的列舉出來(lái),不...
摘要:版權(quán)聲明可轉(zhuǎn)載,但不論任何媒體都需要在轉(zhuǎn)載前與本人溝通,并在轉(zhuǎn)載時(shí)注明出處。的各個(gè)核心模塊以模塊名為目錄名分別存儲(chǔ)在這個(gè)目錄下。下一篇文章會(huì)涉及到和。此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到進(jìn)行溝通,未溝通的均視作侵權(quán)。 寫在前面: 為什么選擇開發(fā)過(guò)程中的 CI 4 作為源碼解讀版本:(1)首先我選 CI 是因?yàn)樗暗姆€(wěn)定版都是相對(duì)比較輕量小巧的,而且可以認(rèn)為是簡(jiǎn)單的。(2)為什么沒有選...
摘要:通過(guò)這個(gè)函數(shù)可以很方便的在程序運(yùn)行期間執(zhí)行很多常見操作。此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到進(jìn)行溝通,未溝通的均視作侵權(quán)。 index.php index.php 是整個(gè)框架的入口文件,也就是說(shuō)所有的請(qǐng)求都要從它這里開始。因?yàn)?index.php 源碼非常簡(jiǎn)潔,那么我們直接放一張?jiān)创a截圖,按著截圖說(shuō)一下源碼。 showImg(https://segmentfault.com/img/re...
閱讀 4259·2023-04-26 02:40
閱讀 2696·2023-04-26 02:31
閱讀 2784·2021-11-15 18:08
閱讀 597·2021-11-12 10:36
閱讀 1461·2021-09-30 09:57
閱讀 5250·2021-09-22 15:31
閱讀 2658·2019-08-30 14:17
閱讀 1308·2019-08-30 12:58