亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

directory search
閱讀前篇 簡(jiǎn)介 Yii 是什么 從 Yii 1.1 升級(jí) 入門 安裝 Yii 運(yùn)行應(yīng)用 第一次問(wèn)候 使用Forms 數(shù)據(jù)庫(kù)應(yīng)用 使用 Gii 生成代碼 進(jìn)階 應(yīng)用結(jié)構(gòu) 概述 入口腳本 應(yīng)用(Applications) 應(yīng)用組件(Application Components) 控制器(Controllers) 模型(Models) 視圖(views) 模塊(Modules) 過(guò)濾器(Filters) 小部件(Widgets) 前端資源(Assets) 擴(kuò)展(Extensions) 請(qǐng)求處理 運(yùn)行概述 啟動(dòng)引導(dǎo)(Bootstrapping) 路由和創(chuàng)建URL 請(qǐng)求(Requests) 響應(yīng)(Responses) Sessions 和 Cookies 錯(cuò)誤處理(Handling Errors) 日志(Logging) 關(guān)鍵概念 組件(Component) 屬性(Property) 事件(Events) 行為(Behaviors) 配置(Configurations) 別名(Aliases) 類自動(dòng)加載(Autoloading) 服務(wù)定位器(Service Locator) 依賴注入容器(Dependency Injection Container) 配合數(shù)據(jù)庫(kù)工作 數(shù)據(jù)庫(kù)訪問(wèn) (Data Access Objects) 查詢生成器(Query Builder) 活動(dòng)記錄(Active Record) 數(shù)據(jù)庫(kù)遷移(Migrations) Sphinx Redis MongoDB Elasticsearch 接收用戶數(shù)據(jù) 創(chuàng)建表單(Creating Forms) 輸入驗(yàn)證(Validating Input) 文件上傳(Uploading Files) 收集列表輸入(Collecting Tabular Input) 多模型的復(fù)合表單(Getting Data for Multiple Models) 顯示數(shù)據(jù) 格式化輸出數(shù)據(jù)(Data Formatting) 分頁(yè)(Pagination) 排序(Sorting) 數(shù)據(jù)提供器(Data Providers) 數(shù)據(jù)小部件(Data Widgets) 客戶端腳本使用(Working with Client Scripts) 主題(Theming) 安全 認(rèn)證(Authentication) 授權(quán)(Authorization) 處理密碼(Working with Passwords) 客戶端認(rèn)證(Auth Clients) 最佳安全實(shí)踐(Best Practices) 緩存 概述 數(shù)據(jù)緩存 片段緩存 頁(yè)面緩存 HTTP 緩存 RESTfull Web服務(wù) 快速入門(Quick Start) 資源(Resources) 控制器(Controllers) 路由(Routing) 格式化響應(yīng)(Response Formatting) 授權(quán)認(rèn)證(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 錯(cuò)誤處理(Error Handling) 開發(fā)工具 調(diào)試工具欄和調(diào)試器 使用Gii生成代碼 生成API文檔 測(cè)試 概述(Overview) 配置測(cè)試環(huán)境(Testing environment setup) 單元測(cè)試(Unit Tests) 功能測(cè)試(Function Tests) 驗(yàn)收測(cè)試(Acceptance Tests) 測(cè)試夾具(Fixtures) 高級(jí)專題 高級(jí)應(yīng)用模板 創(chuàng)建自定義應(yīng)用程序結(jié)構(gòu) 控制臺(tái)命令 核心驗(yàn)證器(Core Validators) 國(guó)際化 收發(fā)郵件 性能優(yōu)化 共享主機(jī)環(huán)境 模板引擎 集成第三方代碼 小部件 Bootstrap 小部件 Jquery UI 助手類 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
characters

視圖

視圖

視圖是?MVC?模式中的一部分。 它是展示數(shù)據(jù)到終端用戶的代碼,在網(wǎng)頁(yè)應(yīng)用中,根據(jù)視圖模板來(lái)創(chuàng)建視圖,視圖模板為PHP腳本文件, 主要包含HTML代碼和展示類PHP代碼,通過(guò)yii\web\View應(yīng)用組件來(lái)管理, 該組件主要提供通用方法幫助視圖構(gòu)造和渲染,簡(jiǎn)單起見,我們稱視圖模板或視圖模板文件為視圖。

創(chuàng)建視圖

如前所述,視圖為包含HTML和PHP代碼的PHP腳本,如下代碼為一個(gè)登錄表單的視圖, 可看到PHP代碼用來(lái)生成動(dòng)態(tài)內(nèi)容如頁(yè)面標(biāo)題和表單,HTML代碼把它組織成一個(gè)漂亮的HTML頁(yè)面。

<?phpuse yii\helpers\Html;
use yii\widgets\ActiveForm;



$this->title = 'Login';
?>
<h1><?= Html::encode($this->title) ?></h1>

<p>Please fill out the following fields to login:</p>

<?php $form = ActiveForm::begin(); ?>
    <?= $form->field($model, 'username') ?>
    <?= $form->field($model, 'password')->passwordInput() ?>
    <?= Html::submitButton('Login') ?><?php ActiveForm::end(); ?>

在視圖中,可訪問(wèn)?$this?指向 yii\web\View 來(lái)管理和渲染這個(gè)視圖文件。

除了?$this之外,上述示例中的視圖有其他預(yù)定義變量如?$model, 這些變量代表從控制器或其他觸發(fā)視圖渲染的對(duì)象?傳入?到視圖的數(shù)據(jù)。

技巧: 將預(yù)定義變量列到視圖文件頭部注釋處,這樣可被IDE編輯器識(shí)別,也是生成視圖文檔的好方法。

安全

當(dāng)創(chuàng)建生成HTML頁(yè)面的視圖時(shí),在顯示之前將用戶輸入數(shù)據(jù)進(jìn)行轉(zhuǎn)碼和過(guò)濾非常重要, 否則,你的應(yīng)用可能會(huì)被跨站腳本?攻擊。

要顯示純文本,先調(diào)用 yii\helpers\Html::encode() 進(jìn)行轉(zhuǎn)碼,例如如下代碼將用戶名在顯示前先轉(zhuǎn)碼:

<?phpuse yii\helpers\Html;
?>

<div class="username">
    <?= Html::encode($user->name) ?>
</div>

要顯示HTML內(nèi)容,先調(diào)用 yii\helpers\HtmlPurifier 過(guò)濾內(nèi)容,例如如下代碼將提交內(nèi)容在顯示前先過(guò)濾:

<?phpuse yii\helpers\HtmlPurifier;
?>

<div class="post">
    <?= HtmlPurifier::process($post->text) ?>
</div>

技巧:HTMLPurifier在保證輸出數(shù)據(jù)安全上做的不錯(cuò),但性能不佳,如果你的應(yīng)用需要高性能可考慮?緩存?過(guò)濾后的結(jié)果。

組織視圖

與?控制器?和?模型?類似,在組織視圖上有一些約定:

  • 控制器渲染的視圖文件默認(rèn)放在?@app/views/ControllerID?目錄下, 其中?ControllerID?對(duì)應(yīng)?控制器 ID, 例如控制器類為PostController,視圖文件目錄應(yīng)為?@app/views/post, 控制器類?PostCommentController對(duì)應(yīng)的目錄為?@app/views/post-comment, 如果是模塊中的控制器,目錄應(yīng)為 yii\base\Module::basePath 模塊目錄下的?views/ControllerID?目錄;
  • 對(duì)于?小部件?渲染的視圖文件默認(rèn)放在?WidgetPath/views?目錄, 其中?WidgetPath?代表小部件類文件所在的目錄;
  • 對(duì)于其他對(duì)象渲染的視圖文件,建議遵循和小部件相似的規(guī)則。

可覆蓋控制器或小部件的 yii\base\ViewContextInterface::getViewPath() 方法來(lái)自定義視圖文件默認(rèn)目錄。

渲染視圖

可在?控制器,?小部件, 或其他地方調(diào)用渲染視圖方法來(lái)渲染視圖, 該方法類似以下格式:


methodName($view, $params = [])

控制器中渲染

在?控制器?中,可調(diào)用以下控制器方法來(lái)渲染視圖:

  • yii\base\Controller::render(): 渲染一個(gè)?視圖名?并使用一個(gè)?布局?返回到渲染結(jié)果。
  • yii\base\Controller::renderPartial(): 渲染一個(gè)?視圖名?并且不使用布局。
  • yii\web\Controller::renderAjax(): 渲染一個(gè)?視圖名?并且不使用布局, 并注入所有注冊(cè)的JS/CSS腳本和文件,通常使用在響應(yīng)AJAX網(wǎng)頁(yè)請(qǐng)求的情況下。
  • yii\base\Controller::renderFile(): 渲染一個(gè)視圖文件目錄或別名下的視圖文件。

例如:

namespace app\controllers;

use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;

class PostController extends Controller{
    public function actionView($id)
    {
        $model = Post::findOne($id);
        if ($model === null) {
            throw new NotFoundHttpException;
        }

        // 渲染一個(gè)名稱為"view"的視圖并使用布局
        return $this->render('view', [
            'model' => $model,
        ]);
    }
}

小部件中渲染

在?小部件?中,可調(diào)用以下小部件方法來(lái)渲染視圖: Within?widgets, you may call the following widget methods to render views.

  • yii\base\Widget::render(): 渲染一個(gè)?視圖名.
  • yii\base\Widget::renderFile(): 渲染一個(gè)視圖文件目錄或別名下的視圖文件。

例如:

namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class ListWidget extends Widget{
    public $items = [];

    public function run()
    {
        // 渲染一個(gè)名為 "list" 的視圖
        return $this->render('list', [
            'items' => $this->items,
        ]);
    }
}

視圖中渲染

可以在視圖中渲染另一個(gè)視圖,可以調(diào)用yii\base\View視圖組件提供的以下方法:

  • yii\base\View::render(): 渲染一個(gè)?視圖名.
  • yii\web\View::renderAjax(): 渲染一個(gè)?視圖名?并注入所有注冊(cè)的JS/CSS腳本和文件,通常使用在響應(yīng)AJAX網(wǎng)頁(yè)請(qǐng)求的情況下。
  • yii\base\View::renderFile(): 渲染一個(gè)視圖文件目錄或別名下的視圖文件。

例如,視圖中的如下代碼會(huì)渲染該視圖所在目錄下的?_overview.php?視圖文件, 記住視圖中?$this?對(duì)應(yīng) yii\base\View 組件:

<?= $this->render('_overview') ?>

其他地方渲染

在任何地方都可以通過(guò)表達(dá)式?Yii::$app->view?訪問(wèn) yii\base\View 應(yīng)用組件, 調(diào)用它的如前所述的方法渲染視圖,例如:

// 顯示視圖文件 "@app/views/site/license.php"echo \Yii::$app->view->renderFile('@app/views/site/license.php');

視圖名

渲染視圖時(shí),可指定一個(gè)視圖名或視圖文件路徑/別名,大多數(shù)情況下使用前者因?yàn)榍罢吆?jiǎn)潔靈活, 我們稱用名字的視圖為?視圖名.

視圖名可以依據(jù)以下規(guī)則到對(duì)應(yīng)的視圖文件路徑:

  • 視圖名可省略文件擴(kuò)展名,這種情況下使用?.php?作為擴(kuò)展, 視圖名?about?對(duì)應(yīng)到?about.php?文件名;
  • 視圖名以雙斜杠?//?開頭,對(duì)應(yīng)的視圖文件路徑為?@app/views/ViewName, 也就是說(shuō)視圖文件在 yii\base\Application::viewPath 路徑下找, 例如?//site/about?對(duì)應(yīng)到?@app/views/site/about.php。
  • 視圖名以單斜杠/開始,視圖文件路徑以當(dāng)前使用模塊?的yii\base\Module::viewPath開始, 如果不存在模塊,使用@app/views/ViewName開始,例如,如果當(dāng)前模塊為user,?/user/create?對(duì)應(yīng)成@app/modules/user/views/user/create.php, 如果不在模塊中,/user/create對(duì)應(yīng)@app/views/user/create.php。
  • 如果 yii\base\View::context 渲染視圖 并且上下文實(shí)現(xiàn)了 yii\base\ViewContextInterface, 視圖文件路徑由上下文的 yii\base\ViewContextInterface::getViewPath() 開始, 這種主要用在控制器和小部件中渲染視圖,例如 如果上下文為控制器SiteController,site/about?對(duì)應(yīng)到?@app/views/site/about.php。
  • 如果視圖渲染另一個(gè)視圖,包含另一個(gè)視圖文件的目錄以當(dāng)前視圖的文件路徑開始, 例如被視圖@app/views/post/index.php?渲染的?item?對(duì)應(yīng)到?@app/views/post/item。

根據(jù)以上規(guī)則,在控制器中?app\controllers\PostController?調(diào)用?$this->render('view'), 實(shí)際上渲染?@app/views/post/view.php視圖文件,當(dāng)在該視圖文件中調(diào)用?$this->render('_overview')?會(huì)渲染?@app/views/post/_overview.php?視圖文件。

視圖中訪問(wèn)數(shù)據(jù)

在視圖中有兩種方式訪問(wèn)數(shù)據(jù):推送和拉取。

推送方式是通過(guò)視圖渲染方法的第二個(gè)參數(shù)傳遞數(shù)據(jù),數(shù)據(jù)格式應(yīng)為名稱-值的數(shù)組, 視圖渲染時(shí),調(diào)用PHP?extract()?方法將該數(shù)組轉(zhuǎn)換為視圖可訪問(wèn)的變量。 例如,如下控制器的渲染視圖代碼推送2個(gè)變量到?report?視圖:$foo = 1?和?$bar = 2。

echo $this->render('report', [
    'foo' => 1,
    'bar' => 2,
]);

拉取方式可讓視圖從yii\base\View視圖組件或其他對(duì)象中主動(dòng)獲得數(shù)據(jù)(如Yii::$app), 在視圖中使用如下表達(dá)式$this->context可獲取到控制器ID, 可讓你在report視圖中獲取控制器的任意屬性或方法,如以下代碼獲取控制器ID。

The controller ID is: <?= $this->context->id ?>?>

推送方式讓視圖更少依賴上下文對(duì)象,是視圖獲取數(shù)據(jù)優(yōu)先使用方式, 缺點(diǎn)是需要手動(dòng)構(gòu)建數(shù)組,有些繁瑣,在不同地方渲染時(shí)容易出錯(cuò)。

視圖間共享數(shù)據(jù)

yii\base\View視圖組件提供yii\base\View::params參數(shù)屬性來(lái)讓不同視圖共享數(shù)據(jù)。

例如在about視圖中,可使用如下代碼指定當(dāng)前breadcrumbs的當(dāng)前部分。

$this->params['breadcrumbs'][] = 'About Us';

在布局文件(也是一個(gè)視圖)中,可使用依次加入到y(tǒng)ii\base\View::params數(shù)組的值來(lái) 生成顯示breadcrumbs:

<?= yii\widgets\Breadcrumbs::widget([
    'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
]) ?>

布局

布局是一種特殊的視圖,代表多個(gè)視圖的公共部分,例如,大多數(shù)Web應(yīng)用共享相同的頁(yè)頭和頁(yè)尾, 在每個(gè)視圖中重復(fù)相同的頁(yè)頭和頁(yè)尾,更好的方式是將這些公共放到一個(gè)布局中, 渲染內(nèi)容視圖后在合適的地方嵌入到布局中。

創(chuàng)建布局

由于布局也是視圖,它可像普通視圖一樣創(chuàng)建,布局默認(rèn)存儲(chǔ)在@app/views/layouts路徑下,?模塊中使用的布局應(yīng)存儲(chǔ)在yii\base\Module::basePath模塊目錄 下的views/layouts路徑下,可配置yii\base\Module::layoutPath來(lái)自定義應(yīng)用或模塊的布局默認(rèn)路徑。

如下示例為一個(gè)布局大致內(nèi)容,注意作為示例,簡(jiǎn)化了很多代碼, 在實(shí)際中,你可能想添加更多內(nèi)容,如頭部標(biāo)簽,主菜單等。

<?phpuse yii\helpers\Html;

?><?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <?= Html::csrfMetaTags() ?>
    <title><?= Html::encode($this->title) ?></title>
    <?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
    <header>My Company</header>
    <?= $content ?>
    <footer>&copy; 2014 by My Company</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

如上所示,布局生成每個(gè)頁(yè)面通用的HTML標(biāo)簽,在<body>標(biāo)簽中,打印$content變量,?$content變量代表當(dāng)yii\base\Controller::render()控制器渲染方法調(diào)用時(shí)傳遞到布局的內(nèi)容視圖渲染結(jié)果。

大多數(shù)視圖應(yīng)調(diào)用上述代碼中的如下方法,這些方法觸發(fā)關(guān)于渲染過(guò)程的事件, 這樣其他地方注冊(cè)的腳本和標(biāo)簽會(huì)添加到這些方法調(diào)用的地方。

  • yii\base\View::beginPage(): 該方法應(yīng)在布局的開始處調(diào)用, 它觸發(fā)表明頁(yè)面開始的 yii\base\View::EVENT_BEGIN_PAGE 事件。
  • yii\base\View::endPage(): 該方法應(yīng)在布局的結(jié)尾處調(diào)用, 它觸發(fā)表明頁(yè)面結(jié)尾的 yii\base\View::EVENT_END_PAGE 時(shí)間。
  • yii\web\View::head(): 該方法應(yīng)在HTML頁(yè)面的<head>標(biāo)簽中調(diào)用, 它生成一個(gè)占位符,在頁(yè)面渲染結(jié)束時(shí)會(huì)被注冊(cè)的頭部HTML代碼(如,link標(biāo)簽, meta標(biāo)簽)替換。
  • yii\web\View::beginBody(): 該方法應(yīng)在<body>標(biāo)簽的開始處調(diào)用, 它觸發(fā) yii\web\View::EVENT_BEGIN_body 事件并生成一個(gè)占位符, 會(huì)被注冊(cè)的HTML代碼(如JavaScript)在頁(yè)面主體開始處替換。
  • yii\web\View::endBody(): 該方法應(yīng)在<body>標(biāo)簽的結(jié)尾處調(diào)用, 它觸發(fā) yii\web\View::EVENT_END_body 事件并生成一個(gè)占位符, 會(huì)被注冊(cè)的HTML代碼(如JavaScript)在頁(yè)面主體結(jié)尾處替換。

布局中訪問(wèn)數(shù)據(jù)

在布局中可訪問(wèn)兩個(gè)預(yù)定義變量:$this?和?$content,前者對(duì)應(yīng)和普通視圖類似的yii\base\View 視圖組件 后者包含調(diào)用yii\base\Controller::render()方法渲染內(nèi)容視圖的結(jié)果。

如果想在布局中訪問(wèn)其他數(shù)據(jù),必須使用視圖中訪問(wèn)數(shù)據(jù)一節(jié)介紹的拉取方式, 如果想從內(nèi)容視圖中傳遞數(shù)據(jù)到布局,可使用視圖間共享數(shù)據(jù)一節(jié)中的方法。

使用布局

如控制器中渲染一節(jié)描述,當(dāng)控制器調(diào)用yii\base\Controller::render() 方法渲染視圖時(shí),會(huì)同時(shí)使用布局到渲染結(jié)果中,默認(rèn)會(huì)使用@app/views/layouts/main.php布局文件。

可配置yii\base\Application::layout 或 yii\base\Controller::layout 使用其他布局文件, 前者管理所有控制器的布局,后者覆蓋前者來(lái)控制單個(gè)控制器布局。 例如,如下代碼使?post?控制器渲染視圖時(shí)使用?@app/views/layouts/post.php?作為布局文件, 假如?layout?屬性沒(méi)改變,控制器默認(rèn)使用?@app/views/layouts/main.php?作為布局文件。

namespace app\controllers;

use yii\web\Controller;

class PostController extends Controller{
    public $layout = 'post';
    
    // ...
}

對(duì)于模塊中的控制器,可配置模塊的 yii\base\Module::layout 屬性指定布局文件應(yīng)用到模塊的所有控制器。

由于layout?可在不同層級(jí)(控制器、模塊,應(yīng)用)配置,在幕后Yii使用兩步來(lái)決定控制器實(shí)際使用的布局。

第一步,它決定布局的值和上下文模塊:

  • 如果控制器的 yii\base\Controller::layout 屬性不為空null,使用它作為布局的值, 控制器的 yii\base\Controller::module模塊 作為上下文模塊。
  • 如果 yii\base\Controller::layout 為空,從控制器的祖先模塊(包括應(yīng)用) 開始找 第一個(gè)yii\base\Module::layout 屬性不為空的模塊,使用該模塊作為上下文模塊, 并將它的yii\base\Module::layout 的值作為布局的值, 如果都沒(méi)有找到,表示不使用布局。

第二步,它決定第一步中布局的值和上下文模塊對(duì)應(yīng)到實(shí)際的布局文件,布局的值可為:

  • 路徑別名 (如?@app/views/layouts/main).
  • 絕對(duì)路徑 (如?/main): 布局的值以斜杠開始,在應(yīng)用的[[yii\base\Application::layoutPath|layout path] 布局路徑 中查找實(shí)際的布局文件,布局路徑默認(rèn)為?@app/views/layouts。
  • 相對(duì)路徑 (如?main): 在上下文模塊的yii\base\Module::layoutPath布局路徑中查找實(shí)際的布局文件, 布局路徑默認(rèn)為yii\base\Module::basePath模塊目錄下的views/layouts?目錄。
  • 布爾值?false: 不使用布局。

布局的值沒(méi)有包含文件擴(kuò)展名,默認(rèn)使用?.php作為擴(kuò)展名。

嵌套布局

有時(shí)候你想嵌套一個(gè)布局到另一個(gè),例如,在Web站點(diǎn)不同地方,想使用不同的布局, 同時(shí)這些布局共享相同的生成全局HTML5頁(yè)面結(jié)構(gòu)的基本布局,可以在子布局中調(diào)用 yii\base\View::beginContent() 和yii\base\View::endContent() 方法,如下所示:

<?php $this->beginContent('@app/views/layouts/base.php'); ?>

...child layout content here...

<?php $this->endContent(); ?>

如上所示,子布局內(nèi)容應(yīng)在 yii\base\View::beginContent() 和 yii\base\View::endContent() 方法之間,傳給 yii\base\View::beginContent() 的參數(shù)指定父布局,父布局可為布局文件或別名。

使用以上方式可多層嵌套布局。

使用數(shù)據(jù)塊

數(shù)據(jù)塊可以在一個(gè)地方指定視圖內(nèi)容在另一個(gè)地方顯示,通常和布局一起使用, 例如,可在內(nèi)容視圖中定義數(shù)據(jù)塊在布局中顯示它。

調(diào)用 yii\base\View::beginBlock() 和 yii\base\View::endBlock() 來(lái)定義數(shù)據(jù)塊, 使用?$view->blocks[$blockID]?訪問(wèn)該數(shù)據(jù)塊,其中$blockID?為定義數(shù)據(jù)塊時(shí)指定的唯一標(biāo)識(shí)ID。

如下實(shí)例顯示如何在內(nèi)容視圖中使用數(shù)據(jù)塊讓布局使用。

首先,在內(nèi)容視圖中定一個(gè)或多個(gè)數(shù)據(jù)塊:

...

<?php $this->beginBlock('block1'); ?>

...content of block1...

<?php $this->endBlock(); ?>

...

<?php $this->beginBlock('block3'); ?>

...content of block3...

<?php $this->endBlock(); ?>

然后,在布局視圖中,數(shù)據(jù)塊可用的話會(huì)渲染數(shù)據(jù)塊,如果數(shù)據(jù)未定義則顯示一些默認(rèn)內(nèi)容。

...
<?php if (isset($this->blocks['block1'])): ?>
    <?= $this->blocks['block1'] ?><?php else: ?>
    ... default content for block1 ...
<?php endif; ?>

...

<?php if (isset($this->blocks['block2'])): ?>
    <?= $this->blocks['block2'] ?><?php else: ?>
    ... default content for block2 ...
<?php endif; ?>

...

<?php if (isset($this->blocks['block3'])): ?>
    <?= $this->blocks['block3'] ?><?php else: ?>
    ... default content for block3 ...
<?php endif; ?>
...

使用視圖組件

yii\base\View視圖組件提供許多視圖相關(guān)特性,可創(chuàng)建yii\base\View或它的子類實(shí)例來(lái)獲取視圖組件, 大多數(shù)情況下主要使用?view?應(yīng)用組件,可在應(yīng)用配置中配置該組件, 如下所示:

[
    // ...
    'components' => [
        'view' => [
            'class' => 'app\components\View',
        ],
        // ...
    ],
]

視圖組件提供如下實(shí)用的視圖相關(guān)特性,每項(xiàng)詳情會(huì)在獨(dú)立章節(jié)中介紹:

  • 主題: 允許為你的Web站點(diǎn)開發(fā)和修改主題;
  • 片段緩存: 允許你在Web頁(yè)面中緩存片段;
  • 客戶腳本處理: 支持CSS 和 JavaScript 注冊(cè)和渲染;
  • 資源包處理: 支持?資源包的注冊(cè)和渲染;
  • 模板引擎: 允許你使用其他模板引擎,如?Twig,?Smarty。

開發(fā)Web頁(yè)面時(shí),也可能頻繁使用以下實(shí)用的小特性。

設(shè)置頁(yè)面標(biāo)題

每個(gè)Web頁(yè)面應(yīng)有一個(gè)標(biāo)題,正常情況下標(biāo)題的標(biāo)簽顯示在?布局中, 但是實(shí)際上標(biāo)題大多由內(nèi)容視圖而不是布局來(lái)決定,為解決這個(gè)問(wèn)題, yii\web\View 提供 yii\web\View::title 標(biāo)題屬性可讓標(biāo)題信息從內(nèi)容視圖傳遞到布局中。

為利用這個(gè)特性,在每個(gè)內(nèi)容視圖中設(shè)置頁(yè)面標(biāo)題,如下所示:

<?php$this->title = 'My page title';
?>

然后在視圖中,確保在?<head>?段中有如下代碼:

<title><?= Html::encode($this->title) ?></title>

注冊(cè)Meta元標(biāo)簽

Web頁(yè)面通常需要生成各種元標(biāo)簽提供給不同的瀏覽器,如<head>中的頁(yè)面標(biāo)題,元標(biāo)簽通常在布局中生成。

如果想在內(nèi)容視圖中生成元標(biāo)簽,可在內(nèi)容視圖中調(diào)用yii\web\View::registerMetaTag()方法,如下所示:

<?php$this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, framework, php']);
?>

以上代碼會(huì)在視圖組件中注冊(cè)一個(gè) "keywords" 元標(biāo)簽,在布局渲染后會(huì)渲染該注冊(cè)的元標(biāo)簽, 然后,如下HTML代碼會(huì)插入到布局中調(diào)用yii\web\View::head()方法處:

<meta name="keywords" content="yii, framework, php">

注意如果多次調(diào)用 yii\web\View::registerMetaTag() 方法,它會(huì)注冊(cè)多個(gè)元標(biāo)簽,注冊(cè)時(shí)不會(huì)檢查是否重復(fù)。

為確保每種元標(biāo)簽只有一個(gè),可在調(diào)用方法時(shí)指定鍵作為第二個(gè)參數(shù), 例如,如下代碼注冊(cè)兩次 "description" 元標(biāo)簽,但是只會(huì)渲染第二個(gè)。

$this->registerMetaTag(['name' => 'description', 'content' => 'This is my cool website made with Yii!'], 'description');
$this->registerMetaTag(['name' => 'description', 'content' => 'This website is about funny raccoons.'], 'description');

注冊(cè)鏈接標(biāo)簽

和?Meta標(biāo)簽?類似,鏈接標(biāo)簽有時(shí)很實(shí)用,如自定義網(wǎng)站圖標(biāo),指定Rss訂閱,或授權(quán)OpenID到其他服務(wù)器。 可以和元標(biāo)簽相似的方式調(diào)用yii\web\View::registerLinkTag(),例如,在內(nèi)容視圖中注冊(cè)鏈接標(biāo)簽如下所示:

$this->registerLinkTag([
    'title' => 'Live News for Yii',
    'rel' => 'alternate',
    'type' => 'application/rss+xml',
    'target="_blank" href' => 'http://www.yiiframework.com/rss.xml/',
]);

上述代碼會(huì)轉(zhuǎn)換成

<link title="Live News for Yii" rel="alternate" type="application/rss+xml" target="_blank" href="http://www.yiiframework.com/rss.xml/">

和 yii\web\View::registerMetaTag() 類似, 調(diào)用yii\web\View::registerLinkTag() 指定鍵來(lái)避免生成重復(fù)鏈接標(biāo)簽。

視圖事件

yii\base\View 視圖組件會(huì)在視圖渲染過(guò)程中觸發(fā)幾個(gè)事件, 可以在內(nèi)容發(fā)送給終端用戶前,響應(yīng)這些事件來(lái)添加內(nèi)容到視圖中或調(diào)整渲染結(jié)果。

  • yii\base\View::EVENT_BEFORE_RENDER: 在控制器渲染文件開始時(shí)觸發(fā), 該事件可設(shè)置 yii\base\ViewEvent::isValid 為 false 取消視圖渲染。
  • yii\base\View::EVENT_AFTER_RENDER: 在布局中調(diào)用 yii\base\View::beginPage() 時(shí)觸發(fā), 該事件可獲取yii\base\ViewEvent::output的渲染結(jié)果,可修改該屬性來(lái)修改渲染結(jié)果。
  • yii\base\View::EVENT_BEGIN_PAGE: 在布局調(diào)用 yii\base\View::beginPage() 時(shí)觸發(fā);
  • yii\base\View::EVENT_END_PAGE: 在布局調(diào)用 yii\base\View::endPage() 是觸發(fā);
  • yii\web\View::EVENT_BEGIN_body: 在布局調(diào)用 yii\web\View::beginBody() 時(shí)觸發(fā);
  • yii\web\View::EVENT_END_body: 在布局調(diào)用 yii\web\View::endBody() 時(shí)觸發(fā)。

例如,如下代碼將當(dāng)前日期添加到頁(yè)面結(jié)尾處:

\Yii::$app->view->on(View::EVENT_END_body, function () {
    echo date('Y-m-d');
});

渲染靜態(tài)頁(yè)面

靜態(tài)頁(yè)面指的是大部分內(nèi)容為靜態(tài)的不需要控制器傳遞動(dòng)態(tài)數(shù)據(jù)的Web頁(yè)面。

可將HTML代碼放置在視圖中,在控制器中使用以下代碼輸出靜態(tài)頁(yè)面:

public function actionAbout(){
    return $this->render('about');
}

如果Web站點(diǎn)包含很多靜態(tài)頁(yè)面,多次重復(fù)相似的代碼顯得很繁瑣, 為解決這個(gè)問(wèn)題,可以使用一個(gè)在控制器中稱為 yii\web\ViewAction 的獨(dú)立操作。 例如:

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller{
    public function actions()
    {
        return [
            'page' => [
                'class' => 'yii\web\ViewAction',
            ],
        ];
    }
}

現(xiàn)在如果你在@app/views/site/pages目錄下創(chuàng)建名為?about?的視圖, 可通過(guò)如下rul顯示該視圖:

http://localhost/index.php?r=site/page&view=about

GET?中?view?參數(shù)告知 yii\web\ViewAction 操作請(qǐng)求哪個(gè)視圖,然后操作在?@app/views/site/pages目錄下尋找該視圖,可配置 yii\web\ViewAction::viewPrefix 修改搜索視圖的目錄。

最佳實(shí)踐

視圖負(fù)責(zé)將模型的數(shù)據(jù)展示用戶想要的格式,總之,視圖

  • 應(yīng)主要包含展示代碼,如HTML, 和簡(jiǎn)單的PHP代碼來(lái)控制、格式化和渲染數(shù)據(jù);
  • 不應(yīng)包含執(zhí)行數(shù)據(jù)查詢代碼,這種代碼放在模型中;
  • 應(yīng)避免直接訪問(wèn)請(qǐng)求數(shù)據(jù),如?$_GET,?$_POST,這種應(yīng)在控制器中執(zhí)行, 如果需要請(qǐng)求數(shù)據(jù),應(yīng)由控制器推送到視圖。
  • 可讀取模型屬性,但不應(yīng)修改它們。

為使模型更易于維護(hù),避免創(chuàng)建太復(fù)雜或包含太多冗余代碼的視圖,可遵循以下方法達(dá)到這個(gè)目標(biāo):

  • 使用?布局?來(lái)展示公共代碼(如,頁(yè)面頭部、尾部);
  • 將復(fù)雜的視圖分成幾個(gè)小視圖,可使用上面描述的渲染方法將這些小視圖渲染并組裝成大視圖;
  • 創(chuàng)建并使用?小部件?作為視圖的數(shù)據(jù)塊;
  • 創(chuàng)建并使用助手類在視圖中轉(zhuǎn)換和格式化數(shù)據(jù)。
Previous article: Next article: