Yii布局(Layouts)


布局代表多個檢視的公用部分。例如,頁首和頁尾。 預設情況下,布局應存放在 views/layouts 檔案夾中。
讓我們看一下基本應用程式模板的主(main )布局 -
<?php
   /* @var $this \yii\web\View */
   /* @var $content string */
   use yii\helpers\Html;
   use yii\bootstrap\Nav;
   use yii\bootstrap\NavBar;
   use yii\widgets\Breadcrumbs;
   use app\assets\AppAsset;
   AppAsset::register($this);
?>

<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang = "<?= Yii::$app->language ?>">
   <head>
      <meta charset = "<?= Yii::$app->charset ?>">
      <meta name = "viewport" content = "width = device-width, initial-scale = 1">
      <?= Html::csrfMetaTags() ?>
      <title><?= Html::encode($this->title) ?></title>
      <?php $this->head() ?>
   </head>
	
   <body>
      <?php $this->beginBody() ?>
         <div class = "wrap">
            <?php
               NavBar::begin([
                  'brandLabel' => 'My Company',
                  'brandUrl' => Yii::$app->homeUrl,
                  'options' => [
                     'class' => 'navbar-inverse navbar-fixed-top',
                  ],
               ]);
					
               echo Nav::widget([
                  'options' => ['class' => 'navbar-nav navbar-right'],
                  'items' => [
                     ['label' => 'Home', 'url' => ['/site/index']],
                     ['label' => 'About', 'url' => ['/site/about']],
                     ['label' => 'Contact', 'url' => ['/site/contact']],
                     Yii::$app->user->isGuest ?
                        ['label' => 'Login', 'url' => ['/site/login']] :
                        [
                           'label' => 'Logout (' . Yii::$app->user->identity->username.')',
                           'url' => ['/site/logout'],
                           'linkOptions' => ['data-method' => 'post']
                        ],
                  ],
               ]);
					
               NavBar::end();
            ?>
            <div class = "container">
               <?= Breadcrumbs::widget([
                  'links' => isset($this->params['breadcrumbs']) ? $this>params
                     ['breadcrumbs'] : [],
               ]) ?>
               <?= $content ?>
            </div>
				
         </div>
			
         <footer class = "footer">
            <div class = "container">
               <p class = "pull-left">© My Company <?= date('Y') ?></p>
               <p class = "pull-right"><?= Yii::powered() ?></p>
            </div>
         </footer>
			
      <?php $this->endBody() ?>
   </body>
</html>
<?php $this->endPage() ?> 

這種布局是所有檢視的通用頁面生成HTML頁面。$content 變數是檢視渲染內容的結果。以下方法引發有關渲染過程事件,以便在其他地方註冊的指令碼和標籤會被適當注入 -

  • head() ? 應在頭部分呼叫。產生一個預留位置,將與定位於頭部位置已註冊的 HTML 來代替。

  • beginBody() ? 應在 body 部分的開頭呼叫。觸發 EVENT_BEGIN_BODY 事件。產生將使用定位在 body 已註冊的HTML,將替換預留位置開始位置。

  • endBody() ? 應在 body 結束部分被呼叫。觸發 EVENT_END_BODY 事件。

     產生一個預留位置,這將有針對性的在 body 的結束位置使用已註冊的HTML來代替。

  • beginPage() ? 應在布局的開頭被呼叫。觸發EVENT_BEGIN_PAGE 事件。

  • endPage() ? 應在布局結束時呼叫。觸發 EVENT_END_PAGE 事件。

建立佈局

第1步 - 在目錄 views/layouts 裡面建立一個名為 newlayout.php 的檔案並使用下面的程式碼。
<?php
   /* @var $this \yii\web\View */
   /* @var $content string */
   use yii\helpers\Html;
   use yii\bootstrap\Nav;
   use yii\bootstrap\NavBar;
   use yii\widgets\Breadcrumbs;
   use app\assets\AppAsset;
   AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang = "<?= Yii::$app->language ?>">
   <head>
      <meta charset = "<?= Yii::$app->charset ?>">
      <meta name = "viewport" content = "width = device-width, initial-scale = 1">
      <?= Html::csrfMetaTags() ?>
      <title><?= Html::encode($this->title) ?></title>
      <?php $this->head() ?>
   </head>

   <body>
      <?php $this->beginBody() ?>
         <div class = "wrap"> 
            <div class = "container">
               <?= $content ?>
            </div>
         </div>
			
         <footer class = "footer">
            <div class = "container">
               <p class = "pull-left">© My Company <?= date('Y') ?></p>
               <p class = "pull-right"><?= Yii::powered() ?></p>
            </div>
         </footer>
      <?php $this->endBody() ?>
   </body>
	
</html>
<?php $this->endPage() ?>
在這裡,我們已經移除了頂部的選單欄。
第2步 - 要將布局應用到SiteController中,需要將 $layout 屬性新增到 SiteController 類。
<?php
   namespace app\controllers;
   use Yii;
   use yii\filters\AccessControl;
   use yii\web\Controller;
   use yii\filters\VerbFilter;
   use app\models\LoginForm;
   use app\models\ContactForm;
   class SiteController extends Controller {
      public $layout = "newlayout";
      /* other methods */
   }
?>
第3步 - 現在,如果到Web瀏覽器開啟 SiteController 中的任何檢視,如開啟URL=> ,您將看到的布局已經發生了變化。

第4步- 要註冊的各種 meta 標籤,可以在內容檢視中呼叫 yii\web\View::registerMetaTag() 函式。
第5步 - 修改 SiteController 的「About」檢視 - views/site/about.php。
<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = '關於我們';
   $this->params['breadcrumbs'][] = $this->title;
   $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, Yii教學, Yii檢視,
      meta, 標籤']);
   $this->registerMetaTag(['name' => 'description', 'content' => '這是一個頁面的描述!'], 'description');
?>
<div class="site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <code><?= __FILE__ ?></code>
</div> 

我們剛剛註冊了兩個 meta 標籤 ? keywords 和 description.

第6步 - 現在開啟 http://localhost:8080/index.php?r=site/about ,你會發現在頁面頭部的 meta 標籤內容如下面的螢幕截圖。

檢視觸發幾個事件 -
  • EVENT_BEGIN_BODY ? 觸發了布局通過呼叫 yii\web\View::beginBody()

  • EVENT_END_BODY ? 觸發了布局通過呼叫 yii\web\View::endBody()

  • EVENT_BEGIN_PAGE ? 觸發了布局通過呼叫 fyii\web\View::beginPage()

  • EVENT_END_PAGE ? 觸發了布局通過呼叫 yii\web\View::endPage()

  • EVENT_BEFORE_RENDER ? 在控制器開始渲染一個檔案時觸發

  • EVENT_AFTER_RENDER ? 渲染檔案後觸發

也可以對這些事件的響應內容插入到檢視。
步驟7- 要顯示當前的日期和時間在 SiteController 的 actionAbout 動作中,以下面的這種方式。
public function actionAbout() {
   Yii::$app->view->on(yii\web\View::EVENT_BEGIN_BODY, function () {
      echo date('Y-m-d H:i:s');
   });
   return $this->render('about');
}
第8步 - 在瀏覽器中存取URL=> http://localhost:8080/index.php?r=site/about,將會看到下面的內容。

要點

為了使檢視更易於管理,你應該 -
  • 將複雜的檢視分成幾個小塊檔案
  • 使用公用的HTML程式碼部分(頁首,頁尾,選單等)的布局
  • 使用小部件-widgets
檢視應該 -
  • 包含HTML和簡單的PHP程式碼格式化和呈現資料。
  • 無處理請求
  • 不修改模型屬性
  • 不執行資料庫查詢