视图(View)
视图(View)这一部分比较多,总共包括11个知识点:
- 基本定义
- 部件(Widget)
- 安全
- 模板引擎
- 在模板中使用视图对象
- 设置页面标题
- 添加meta标签
- 注册连接标签
- 注册CSS
- 注册脚本
- 注册asset bundles
- 布局(Layout)
- 局部(Partial)
- 访问上下文
- 静态页面
- 缓存区块
- 自定义视图组件
视图基本上就是我们所说的在views文件夹中的显示前台页面的模板。 另外还有一个对应的视图类(yii\web\view)这个是在Yii2中新增加的,我们在views中的模板文件中看到的$this对象就是Yii2中的视图对象。 我们下面就用模板来称呼前台view中的视图,以便和yii\web\view这个视图类混淆。
默认情况下,Yii使用php语言来解析模板,也就是说在views中的模板里面直接用php代码来输出数据。
在模板页面最好不要包含复杂的php逻辑代码,应该尽可能的把它们放到控制器或者部件里面去实现。
模板一般在控制器中的动作(Action)里执行 render() 方法的时候调用。
- public function actionIndex()
- {
- return $this->render('index', ['username' => 'samdark']);
- }
在这里只需要添加模板的文件名就可以了,不用加路径以及后缀。Yii会在当前控制器的 ID (如 site )目录下搜索这个模板文件。
如当前控制器是SiteController,那个将会在views/site目录下面搜索index文件。
如果想知道Yii是怎样查找视图文件的可以查看 yii\base\Controller::render()
第二个参数是一个name-value的数组。这个数组会直接传递到views目录中的模板文件里面,并且name可直接作为php变量来引用,value就是对应的变量的值。如上面的index视图文件为 views/site/index.php 。
- <p>Hello, <?= $username ?>!</p>
除了上面说的render()方法外,在yii\web\Controller中还有几种加载视图的方法:
- render():渲染一个模板,然后对渲染的结果应用布局文件。这个是通常用来渲染一个完整的页面。
- renderPartial():仅仅渲染一个模板,不对渲染的结果使用布局文件。通常用来渲染页面的局部。
- renderAjax():也是只渲染模板,不使用布局文件,但会加载所有注册的js/css等脚本文件。通常把渲染的html代码作为Ajax请求的响应。
- renderFile()渲染一个模板文件,基本和renderPartial()功能一样,只不过这里要求的是文件的路径而不是文件的名称。
部件是视图中的独立的区块,用来把一些复杂的逻辑、页面显示及相应的功能实到一个独立的组件中。
Yii内置很多常用的部件,如表单(active form),面包屑(breadcrumbs),菜单(menu)以及对bootstrap的包装。另外在某些扩展组件中也提供了部件,如官方的jQueryUI组件。
下面是在视图文件中使用部件的例子:
- // Note that you have to "echo" the result to display it
- //输出部件Menu中的内容
- echo \yii\widgets\Menu::widget(['items' => $items]);
- // Passing an array to initialize the object properties
- //可往部件中传递参数来初始化部件
- $form = \yii\widgets\ActiveForm::begin([
- 'options' => ['class' => 'form-horizontal'],
- 'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],
- ]);
- ... form inputs here ...
- \yii\widgets\ActiveForm::end();
3、安全
最主要的安全规则之一就是对所有的输出进行编码,如果违反这一规则将会导致脚本执行漏洞,最大可能会导致XSS跨域站点攻击以到管理员密码。
Yii提供了一系列的工具来帮助你实现对输出的编码。最基本的过滤标签的代码如下:
- <?php
- use yii\helpers\Html;
- ?>
- <div class="username">
- <?= Html::encode($user->name) ?>
- </div>
- <?php
- use yii\helpers\HtmlPurifier;
- ?>
- <div class="post">
- <?= HtmlPurifier::process($post->text) ?>
- </div>
4、模板引擎
我们还提供了2个官方的模板引擎 Smarty 和 Twig ,想了解更多情况可以查看这里使用模板引擎(Using template engines )
5、在模板中使用视图对象
yii\web\View 组件的对象可以在模板里面直接使用,即模板视图中的 $this 变量。有了这个变量可以进行更多的操作,如设置页面的标题、meta信息、脚本和访问当前的上下文对象。
1、设置页面标题
- $this->title = 'My page title';
meta标签如encoding、keywords、description等
- $this->registerMetaTag(['encoding' => 'utf-8']);
- <meta encoding="utf-8">
- $this->registerMetaTag(['name' => 'description', 'content' => 'This is my cool website made with Yii!'], 'meta-description');
- $this->registerMetaTag(['name' => 'description', 'content' => 'This website is about funny raccoons.'], 'meta-description');
- <meta name="description" content="This website is about funny raccoons.">
<link> 标签在很多情况下都很有用,如自定义favicon、RSS等等
- $this->registerLinkTag([
- 'title' => 'Lives News for Yii Framework',
- 'rel' => 'alternate',
- 'type' => 'application/rss+xml',
- 'href' => 'http://www.yiiframework.com/rss.xml/',
- ]);
- <link title="Lives News for Yii Framework" rel="alternate" type="application/rss+xml" href="http://www.yiiframework.com/rss.xml/" />
4、注册CSS
还可以用视图对象中的 registerCss() 或 registerCssFile() 来注册CSS。 registerCss() 方法用来注册CSS代码段, registerCssFile() 用来注册一个外部CSS文件。
- $this->registerCss("body { background: #f00; }");
- <style>
- body { background: #f00; }
- </style>
- $this->registerCssFile("http://example.com/css/themes/black-and-white.css", [BootstrapAsset::className()], ['media' => 'print'], 'css-print-theme');
- 第一个参数指定要添加的css文件
- 第二个参数指定这个css文件依赖的BootstrapAsset。意思是说在BootstrapAsset里面的css文件加载完成之后才加载刚才指定的css文件。如果没有指定依赖项那么这个css文件和BootstrapAsset里面的css文件的将没有先后顺序。
- 第三个参数设置<link>标签的其它属性的值。
- 最后一个参数用来唯一标识这个css文件。如果没有指定的话将会用这个css的URL连接。
5、注册脚本
利用 yii\web\View 还可以注册脚本文件。注册脚本也有2个方法, registerJs() 用来注册内部js代码, registerJsFile() 用来注册外部Js文件。内部js代码可用于配置或者动态生成代码的时候,
- $this->registerJs("var options = ".json_encode($options).";", View::POS_END, 'my-options');
第二个参数指定js脚本添加到页面的位置。
- View::POS_HEAD 在头部添加
- View::POS_BEGIN 在[color=Red]<body>[/color]标签开始之后
- View::POS_END 在[color=Red]</body>[/color]标签结束之前
- View::POS_READY 在document [color=Red]ready[/color] event 准备好之后,这个会自动注册并使用jQuery。
- View::POS_LOAD 在 document [color=Red]load[/color] event 准备好之后, 这个会自动注册并使用jQuery。
外部Js代码添加如下
- $this->registerJsFile('http://example.com/js/main.js', [JqueryAsset::className()]);
和 registerCssFile() 一样,我们也建议你使用 asset bundles 来注册外部js文件而不是使用 registerJsFile() 。
6、注册asset bundles
如先前所提到的,在页面中最好使用 asset bundles ,而不是直接在页面中使用css和javascript。关于asset bundles的相关信息可以查看 asset manager 。
使用已经定义的asset bundles代码如下
- \frontend\assets\AppAsset::register($this);
在一个应用中如果大部分的页面显示的内容基本相同,那么使用全局布局文件无疑是最好的选择。
布局文件中一般包括头部、尾部、主菜单以及其它在所有页面公共的部分。下面这个是最基本的一个布局文件。
- <?php
- use yii\helpers\Html;
- ?>
- <?php $this->beginPage() ?>
- <!DOCTYPE html>
- <html lang="<?= Yii::$app->language ?>">
- <head>
- <meta charset="<?= Yii::$app->charset ?>"/>
- <title><?= Html::encode($this->title) ?></title>
- <?php $this->head() ?>
- </head>
- <body>
- <?php $this->beginBody() ?>
- <div class="container">
- <?= $content ?>
- </div>
- <footer class="footer"> 2013 me :)</footer>
- <?php $this->endBody() ?>
- </body>
- </html>
- <?php $this->endPage() ?>
在代码的开始,我们使用php的方法 use 来引入 Html 帮助类。这个类主要功能就是用于对输出的结果进行编码。
另外还有一些特殊的方法如 beginPage()/endPage() , head() , beginBody()/endBody() 这些在渲染页面的时候都触发相应的事件。你可以在这些事件里面注册脚本、连接以及处理页面等等。
7、局部视图(Partial)
有时候一些Html代码需要在多个视图页面使用,大多部情况下这些Html代码太简单了以至于创建部件(Widget)有点浪费。
局部视图也是视图文件,它也存在于 views 目录下面并且文件名以 “_” 开头。例如我们要显示所有用户信息的列表,同时还在其它地方显示一个单独用户的信息。
首先定义用户信息的局部文件 _profile.php
- <?php
- use yii\helpers\Html;
- ?>
- <div class="profile">
- <h2><?= Html::encode($username) ?></h2>
- <p><?= Html::encode($tagline) ?></p>
- </div>
- <div class="user-index">
- <?php
- foreach ($users as $user) {
- echo $this->render('_profile', [
- 'username' => $user->name,
- 'tagline' => $user->tagline,
- ]);
- }
- ?>
- </div>
- echo $this->render('_profile', [
- 'username' => $user->name,
- 'tagline' => $user->tagline,
- ]);
另外也可以在路径中使用别名,如 @app/views/common/_profile
除了另外还可以使用绝对路径加上视图的名称如 /user/_profile 、 //user/_profile 。绝对路径要以“/”或者"//"开头。如果以 “/” 开头将会从当前模块的view路径里面查找,如果以 "//" 开头,前者会从应用程序的view路径中查找
8、访问上下文
视图文件一般由控制器或者部件来调用,在这两种情况下我们都可以通过视图对象的 $this->context 来得到相应的控制器或者部件。例如想在当前的视图中得到路由信息可以用
- echo $this->context->getRoute();
9、静态页面
如果需要渲染一个静态页面可以使用 ViewAction 类。它会根据用户的设置调用这个action来显示相应的视图文件。
首先在控制器里面的 actions 里面
- class SiteController extends Controller
- {
- public function actions()
- {
- return [
- 'static' => [
- 'class' => '\yii\web\ViewAction',
- ],
- ];
- }
- //...
- }
- //index.php
- <h1>Hello, I am a static page!</h1>
默认情况下是通过GET参数中的 view 变量来显示相应的静态文件的。如果URL为 /index.php?r=site/static?&view=about 那么将会显示 @app/views/site/pages/about.php 静态文件。
静态文件默认按照如下顺序来显示
- 获取GET参数:view
- 如果没有指定view参数,将使用默认的index.php静态文件。
- 在静态文件的目录中查找相应的文件(viewPrefix):pages为目录
- 使用相应的布局文件。
10、缓存区块
关于对区块的缓存可以查看缓存章节
11、自定义视图组件
由于view也是一个应用程序组件,所以你可以替换为你自己自定义的组件。自定义的视图组件一般从 yii\base\View 或者 yii\web\View 继承。可以在应用程序的配置文件(如 config/web.php )中进行设置:
- return [
- // ...
- 'components' => [
- 'view' => [
- 'class' => 'app\components\View',
- ],
- // ...
- ],
- ];