【Fizzday05】構(gòu)建MVC之視圖View

View的職責(zé)范圍:

view 干的事, 不多也不少, 就是通過(guò)view加載視圖, 同時(shí)分配變量到視圖, 所以, 他所做的工作基本包括:

  1. 加載視圖, 所以需要有個(gè)加載視圖的方法, 我們定義為 make()
  2. 分配變量, 我們需要有個(gè)方法可以承載變量, 定義為 with()
  3. 我們要讓他能夠以json的格式作為api返回

示例

還是 TestController.php 的 test2 方法

<?php
namespace App\Controller;
use Fizzday\FizzDB\DB;
use Fizzday\FizzView\FizzView as View;

class TestControlelr extends BaseController;
{
    public function test()
    {
        $users = DB::table('users')->where('id', 1)->first();
        
        print_r($users);
    }
    
    public function test2()
    {
        View::make('test.tes2')
            ->with('name', 'xiaoming')
            ->withAge(22);
    }
}

模板中使用變量

<span>名字: <?=$name;?> </span>
<span>年齡: <?=$age;?> </span>

說(shuō)明: 這里使用了魔術(shù)方法解析 withAge 為 age. 同時(shí)指定模板的時(shí)候,可以用點(diǎn)語(yǔ)法(test.test2),或者(test/test2),當(dāng)然可以不指定,自動(dòng)模板會(huì)找對(duì)應(yīng)的目錄下的文件

完善類(lèi)

綜合這些, 我們來(lái)完善一個(gè)簡(jiǎn)單的View類(lèi):

<?php

namespace Fizzday\FizzView;

// 自動(dòng)分配模板的時(shí)候, 需要引入路由
use Fizzday\FizzRoute\Route;

class View
{
    // 模板文件路徑
    public static $viewPath = [];
    // 分配的變量數(shù)組
    public static $data = [];
    // 是否返回解析后的文本(發(fā)郵件等情況下會(huì)使用到), 默認(rèn)false
    public static $return = false;

    /**
     * 分配模板
     * @param  sting $viewName 模板名字, 如: admin.index或者admin/index
     * @param  boolean $type 是否返回為文本
     * @return mixed            輸出或返回文本
     */
    public static function make($viewName = null, $type = false)
    {
        if (!defined('VIEW_PATH')) die("未定義 VIEW_PATH 常量");
        if (!$viewName) { // 自動(dòng)分配模板
            if (!class_exists("Route")) die('沒(méi)有保存 autoView 數(shù)據(jù)對(duì)應(yīng)的類(lèi) Route ');
            // 檢查是否存在 $autoView 變量
            if (!array_key_exists('autoView', get_class_vars("Route"))) die('獲取不到保存自動(dòng)模板的變量, 檢查 Route::$autoView 是否存在');

            $autoView = Route::$autoView;
            $viewName = str_replace('\\', '.', str_replace('controller', '', strtolower($autoView['class']))) . '.' . $autoView['function'];
        }
        $viewFilePath = VIEW_PATH . str_replace('.', '/', $viewName) . '.php';

        if (is_file($viewFilePath)) static::$viewPath[] = $viewFilePath;
        else die("View file does not exist!");

        if ($type) static::$return = true;
        return new static;
    }

    /**
     * 分配變量
     * @param  sting $key 變量key
     * @param  string $value 變量值
     * @return obj          返回鏈?zhǔn)讲僮鲗?duì)象
     */
    public static function with($key, $value = null)
    {
        if (is_array($key) && !empty($key)) {
            foreach ($key as $k => $v) {
                static::$data[$k] = $v;
            }
        } else static::$data[$key] = $value;

        return new static;
    }

    /**
     * 捕獲未定義的方法
     * @param  sting $method 變量key和with組合
     * @param  mixed $parameters 變量值
     * @return obj             [description]
     */
    public function __call($method, $parameters)
    {
        if (start_with($method, 'with')) static::with(lcfirst(substr_replace($method, '', 0, 4)), $parameters[0]);
        else die("Function [$method] does not exist!");
        return new static;
    }

    /**
     * 渲染變量到模板
     * @return mixed 最終頁(yè)面
     */
    public static function run()
    {
        // 獲取模板文件
        $viewPath = static::$viewPath;
        $data = static::$data;
        $return = static::$return;

        if ($viewPath) {
            // 分配變量
            extract($data);               // 抽取數(shù)組中的變量
            if (ob_get_contents()) ob_end_clean();              //關(guān)閉頂層的輸出緩沖區(qū)內(nèi)容
            ob_start();                  // 開(kāi)始一個(gè)新的緩沖區(qū)

            foreach ($viewPath as $v) {
                require $v;                //加載解析后的文件
            }

            $content = ob_get_contents();// 獲得緩沖區(qū)的內(nèi)容
            if (ob_get_contents()) ob_end_clean();              // 關(guān)閉緩沖區(qū)
            ob_start();                   //開(kāi)始新的緩沖區(qū),給后面的程序用

            // 重置變量
            static::reset();

            // 處理返回
            if ($return) return $content;       // 返回文本许溅。
            else echo $content;
        }
    }

    /**
     * 重置模板輸出信息
     * @return [type] [description]
     */
    private static function reset()
    {
        static::$viewPath = [];
        static::$data = [];
        static::$return = false;
    }
}

這里為了使用方便, 加入了自動(dòng)模板功能, 也就是使用 make() 方法未指定模板時(shí), 會(huì)自動(dòng)到控制器名字對(duì)應(yīng)的目錄下自動(dòng)去尋找方法名對(duì)應(yīng)的文件. 同時(shí), 在FizzRoute.php中添加了自動(dòng)模板的支持

到這里, 一個(gè)模板功能就加入了框架中, 但讓, 這里為了簡(jiǎn)單, 沒(méi)有做模板簡(jiǎn)化定義解析, 用的php原生模板語(yǔ)法, 后邊會(huì)一點(diǎn)點(diǎn)探究

配置

同樣的, 為了更加簡(jiǎn)單, 以及做好分離, 我們加入可配置選項(xiàng), 通過(guò)一個(gè)配置控制是否啟用模板, 減少不必要的模板初始化加載消耗

    1. 更改 ~/fizzday/bootstrap/boot.php 文件, 前邊講過(guò)了, 這是統(tǒng)一驅(qū)動(dòng)文件, 所以, 我們把 view 的驅(qū)動(dòng)也放到這里, 方便統(tǒng)一管理
<?php
// 項(xiàng)目的源碼根目錄
define('BASE_PATH', __DIR__ . '/../');
// 配置目錄
define('CONF_PATH', BASE_PATH . 'config/');
// 請(qǐng)求composer入口文件
require BASE_PATH . 'vendor/autoload.php';
// 路由目錄
define('ROUTE_PATH', BASE_PATH.config('config.path.route').'/');
// 緩存目錄
define('CACHE_PATH', BASE_PATH.config('config.path.cache').'/');
// 取別名, 這樣就不需要在 routes/routes.php 中 use FizzRoute 了
class_alias('\\Fizzday\\FizzRoute\\Route', 'Route');

// 引入路由
require ROUTE_PATH . 'route.php';

// 驅(qū)動(dòng)路由
Route::dispatch();

// 模板啟用
if (config('config.switch.view') == 'on') {
    // 模板目錄
    define('VIEW_PATH', BASE_PATH.config('config.path.view').'/');

    class_alias('\\Fizzday\\FizzView\\View', 'View');

    // 驅(qū)動(dòng) view
    View::run();
}

我們可以看到, 尾部加入了 view 的相關(guān)驅(qū)動(dòng), 同時(shí)在公共配置文件~/fizzday/config/config.php 配置view的開(kāi)關(guān)
到此, 一個(gè)包含mvc結(jié)構(gòu)的框架就完全完成了, 可以做基本的使用了, 同時(shí)可以高度自由的DIY, 如果只是學(xué)習(xí)交流, 看到這里就可以了.
后續(xù)的文章會(huì)涉及到高級(jí)應(yīng)用和優(yōu)化, 比如: webapi常用的JWT認(rèn)證來(lái)滿足異步通信, 緩存路由,配置,數(shù)據(jù)庫(kù)信息等提高執(zhí)行效率, 增加高可用性, 配置集群機(jī)器支持多slave數(shù)據(jù)庫(kù)等等等等......

框架github地址
個(gè)人主頁(yè)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冒掌,老刑警劉巖血巍,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異践美,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)找岖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)陨倡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人许布,你說(shuō)我怎么就攤上這事兴革。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵杂曲,是天一觀的道長(zhǎng)庶艾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)擎勘,這世上最難降的妖魔是什么咱揍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮货抄,結(jié)果婚禮上述召,老公的妹妹穿的比我還像新娘。我一直安慰自己蟹地,他們只是感情好积暖,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著怪与,像睡著了一般夺刑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上分别,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天遍愿,我揣著相機(jī)與錄音,去河邊找鬼耘斩。 笑死沼填,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的括授。 我是一名探鬼主播坞笙,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荚虚!你這毒婦竟也來(lái)了薛夜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤版述,失蹤者是張志新(化名)和其女友劉穎梯澜,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體渴析,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晚伙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俭茧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咆疗。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖恢恼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胰默,我是刑警寧澤场斑,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布漓踢,位于F島的核電站,受9級(jí)特大地震影響漏隐,放射性物質(zhì)發(fā)生泄漏喧半。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一青责、第九天 我趴在偏房一處隱蔽的房頂上張望挺据。 院中可真熱鬧,春花似錦脖隶、人聲如沸扁耐。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)婉称。三九已至,卻和暖如春构蹬,著一層夾襖步出監(jiān)牢的瞬間王暗,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工庄敛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俗壹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓藻烤,卻偏偏與公主長(zhǎng)得像绷雏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子隐绵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,841評(píng)論 25 707
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,778評(píng)論 6 342
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理之众,服務(wù)發(fā)現(xiàn),斷路器依许,智...
    卡卡羅2017閱讀 134,637評(píng)論 18 139
  • 海倫公主閱讀 141評(píng)論 0 0
  • http://www.hangge.com/blog/cache/detail_1174.html
    saman0閱讀 187評(píng)論 0 0