完全指南:模板创建、渲染机制与布局系统实战)
后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载视图View是 Yii 2 MVC 架构中的表现层负责把模型数据以 HTML 形式呈现给终端用户。本文基于 Yii 2 官方指南「Представлення / Views」章节结合 framework/base/View.php、framework/web/View.php、framework/base/Controller.php 等核心源码系统讲解视图模板的创建规范、五种渲染场景、命名视图解析规则、布局Layout系统、视图组件的高级用法与渲染事件帮助你从零掌握在 Yii 2 项目中组织、渲染和定制视图的完整实战能力。视图在 MVC 中的定位视图是 MVC 架构 的一部分是负责向终端用户展示数据的代码。在 Web 应用中视图通常以**视图模板view template**的形式存在——即主要包含 HTML 代码与少量表现层 PHP 代码的脚本文件。视图由view应用组件即 [[yii\web\View]]类定义见 framework/web/View.php统一管理。该组件提供了大量常用方法用于简化视图的组合composition与渲染rendering。在日常开发中视图模板或视图模板文件通常被简称为视图。创建视图视图本质上就是一个混合了 HTML 与 PHP 的脚本文件。下面是一个典型的登录表单视图PHP 代码用于生成动态内容如页面标题、表单HTML 代码负责将它们组织成可呈现的页面?php use yii\helpers\Html; use yii\widgets\ActiveForm; /** * var \yii\web\View $this * var \yii\widgets\ActiveForm $form * var \app\models\LoginForm $model */ $this-title Вхід; // 登录 ? h1? Html::encode($this-title) ?/h1 pБудь ласка, заповніть наступні поля для входу:/p ?php $form ActiveForm::begin(); ? ? $form-field($model, username) ? ? $form-field($model, password)-passwordInput() ? ? Html::submitButton(Увійти) ? ?php ActiveForm::end(); ?在视图内部可以通过$this访问管理并渲染该模板的视图组件即yii\web\View实例。除了$this视图中还可能存在其他预定义变量如上述示例中的$model它们代表由控制器或其他触发视图渲染的对象推入视图的数据。提示在视图开头用注释块列出预定义变量IDE 即可识别这些变量自动补全这也是为视图编写文档的好习惯。安全性编码与过滤输出创建生成 HTML 页面的视图时必须在展示前对来自终端用户的数据进行编码和/或过滤否则应用可能遭受跨站脚本XSS攻击。展示纯文本——先调用 [[yii\helpers\Html::encode()]]实现见 framework/helpers/BaseHtml.php进行编码?php use yii\helpers\Html; ? div classusername ? Html::encode($user-name) ? /div展示 HTML 内容——使用 [[yii\helpers\HtmlPurifier]]实现见 framework/helpers/HtmlPurifier.php先过滤可能危险的标签与属性?php use yii\helpers\HtmlPurifier; ? div classpost ? HtmlPurifier::process($post-text) ? /div提示HTMLPurifier 在保证输出安全方面表现出色但运行较慢。若应用对性能有高要求应考虑缓存过滤结果可与片段缓存结合使用。视图的组织约定与控制器和模型类似视图的存放位置遵循明确约定由控制器渲染的视图默认放在app/views/ControllerID目录下其中ControllerID对应控制器 ID。例如控制器类PostController对应app/views/postPostCommentController对应app/views/post-comment若控制器属于某个模块则放在模块[[yii\base\Module::basePath|目录]]下的views/ControllerID。由部件widget渲染的视图默认放在WidgetPath/views目录下其中WidgetPath是部件类文件所在目录。由其他对象渲染的视图建议遵循与部件相同的约定。这些默认目录可以通过重写控制器或部件的 [[yii\base\ViewContextInterface::getViewPath()]] 方法接口定义见 framework/base/ViewContextInterface.php来自定义。控制器默认的getViewPath()实现在 framework/base/Controller.php它返回模块视图路径 DIRECTORY_SEPARATOR 控制器 ID。渲染视图可以在控制器、部件或任何其他地方调用视图渲染方法。所有渲染方法共享如下签名/** * param string $view 视图名或文件路径取决于具体方法 * param array $params 传给视图的数据 * return string 渲染结果 */ methodName($view, $params [])在控制器中渲染控制器提供以下渲染方法方法说明[[yii\base\Controller::render()|render()]]渲染命名视图并对结果应用布局[[yii\base\Controller::renderPartial()|renderPartial()]]渲染命名视图不应用任何布局[[yii\web\Controller::renderAjax()|renderAjax()]]渲染命名视图不应用布局但注入所有已注册的 JS/CSS 脚本与文件常用于响应 AJAX 请求[[yii\base\Controller::renderFile()|renderFile()]]按视图文件路径或别名渲染视图[[yii\base\Controller::renderContent()|renderContent()]]渲染静态字符串并将其嵌入当前适用的布局自 2.0.1 起可用从源码看framework/base/Controller.phprender()的内部实现是两步走先调用getView()-render($view, $params, $this)渲染内容视图再把结果作为$content变量交给renderContent()套上布局renderPartial()则直接调用视图组件的render()完全不碰布局。控制器渲染示例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; } // 渲染名为 view 的视图并对其应用布局 return $this-render(view, [ model $model, ]); } }在部件中渲染部件Widget提供两个渲染方法定义见 framework/base/Widget.php[[yii\base\Widget::render()|render()]]渲染命名视图。[[yii\base\Widget::renderFile()|renderFile()]]按视图文件路径或别名渲染视图。namespace app\components; use yii\base\Widget; use yii\helpers\Html; class ListWidget extends Widget { public $items []; public function run() { // 渲染名为 list 的视图 return $this-render(list, [ items $this-items, ]); } }在视图中渲染视图可以在一个视图内渲染另一个视图调用视图组件提供的以下方法[[yii\base\View::render()|render()]]渲染命名视图。[[yii\web\View::renderAjax()|renderAjax()]]渲染命名视图并注入所有已注册的 JS/CSS 脚本与文件常用于响应 AJAX 请求。[[yii\base\View::renderFile()|renderFile()]]按视图文件路径或别名渲染视图。例如下面的代码在视图中渲染与当前视图同目录下的_overview.php文件。注意视图中的$this指向视图组件yii\base\View? $this-render(_overview) ?在其他地方渲染任何位置都可以通过Yii::$app-view获取视图应用组件然后调用上述方法渲染视图。例如// 显示视图文件 app/views/site/license.php echo \Yii::$app-view-renderFile(app/views/site/license.php);命名视图渲染视图时既可以用视图名也可以用视图文件路径/别名。大多数场景下使用前者更简洁灵活这类用名称指定的视图称为命名视图named views。视图名按照以下规则解析为对应的视图文件路径解析逻辑的完整实现见 framework/base/View.php 的findViewFile()可省略扩展名省略时默认使用.php。例如视图名about对应文件about.php。以双斜杠//开头对应路径为app/views/ViewName即在[[yii\base\Application::viewPath|应用视图目录]]下查找。例如//site/about解析为app/views/site/about.php。以单斜杠/开头路径 当前活动模块的[[yii\base\Module::viewPath|视图目录]] 视图名若无活动模块则使用app/views/ViewName。例如当前活动模块为user时/user/create解析为app/modules/user/views/user/create.php无活动模块时解析为app/views/user/create.php。带渲染上下文若视图在带有[[yii\base\View::context|上下文]]的情况下渲染且上下文实现了 [[yii\base\ViewContextInterface]]则路径 上下文的[[yii\base\ViewContextInterface::getViewPath()|视图目录]] 视图名。这主要适用于控制器和部件内部的渲染。例如上下文是SiteController时about解析为app/views/site/about.php。在视图内渲染视图若视图 A 内渲染视图 B则 A 所在目录会加在 B 的名称之前。例如在app/views/post/index.php中渲染item解析为app/views/post/item.php。根据上述规则在控制器app\controllers\PostController中调用$this-render(view)实际渲染的是app/views/post/view.php而在该视图中调用$this-render(_overview)渲染的是app/views/post/_overview.php。视图中的数据访问推Push与拉Pull视图内访问数据有两种方式推与拉。推push方式把数据作为第二个参数传给渲染方法数据用键值对数组表示。渲染时 PHP 会对该数组执行extract()函数把数组提取为视图内的变量。例如下面代码向report视图推入两个变量$foo 1与$bar 2echo $this-render(report, [ foo 1, bar 2, ]);拉pull方式主动从视图组件或其他视图中可访问的对象如Yii::$app获取数据。例如通过$this-context拿到控制器对象从而访问控制器的任意属性与方法Ідентифікатор контролера: ? $this-context-id ?推方式通常是首选因为它让视图减少对上下文对象的依赖缺点是每次都要手工构造数据数组当视图被多处共享渲染时会比较繁琐且容易出错。视图间共享数据视图组件提供了 [[yii\base\View::params|params]] 属性定义见 framework/base/View.php用于在视图之间共享数据。例如在about视图中可以这样追加面包屑的当前片段$this-params[breadcrumbs][] Про нас;然后在同样是视图的布局文件中用这些数据渲染面包屑? yii\widgets\Breadcrumbs::widget([ links isset($this-params[breadcrumbs]) ? $this-params[breadcrumbs] : [], ]) ?布局Layout系统布局是一种特殊类型的视图代表多个视图共有的部分。例如大多数 Web 应用的页面共享相同的页头与页脚。与其在每个视图里重复写页头页脚不如在布局中写一次并把内容视图的渲染结果嵌入到布局的合适位置。创建布局布局本质上也是视图创建方式与普通视图相同。默认布局存放在app/views/layouts目录模块内使用的布局放在模块[[yii\base\Module::basePath|目录]]下的views/layouts。可以通过配置应用或模块的 [[yii\base\Module::layoutPath]] 属性自定义默认布局目录。下面是一个典型的布局示例为便于说明已大幅简化实际项目中通常会加入head标签、主菜单等内容?php use yii\helpers\Html; /** * var \yii\web\View $this * var string $content */ ? ?php $this-beginPage() ? !DOCTYPE html html langen head meta charsetUTF-8/ ? Html::csrfMetaTags() ? title? Html::encode($this-title) ?/title ?php $this-head() ? /head body ?php $this-beginBody() ? headerМоя компанія/header ? $content ? footerМоя компанія copy; 2014/footer ?php $this-endBody() ? /body /html ?php $this-endPage() ?布局生成所有页面共有的 HTML 标签在body部分布局输出$content变量——它代表内容视图的渲染结果由 [[yii\base\Controller::render()]] 调用时推入布局。大多数布局应按上面的代码调用以下方法这些方法主要触发渲染过程相关的事件使其他地方注册的脚本与标签被正确注入到对应位置[[yii\base\View::beginPage()|beginPage()]]必须在布局最开头调用触发 [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]] 事件常量为beginPage见 framework/base/View.php标志页面开始。[[yii\base\View::endPage()|endPage()]]必须在布局末尾调用触发 [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]] 事件见 framework/base/View.php标志页面结束。[[yii\web\View::head()|head()]]必须在 HTML 页面的head部分调用。它输出一个占位符PH_HEAD页面渲染完成时被注册的头部 HTML 代码如 link 标签、meta 标签替换见 framework/web/View.php。[[yii\web\View::beginBody()|beginBody()]]必须在body部分开头调用触发 [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]] 事件并输出针对 body 开始位置的占位符见 framework/web/View.php。[[yii\web\View::endBody()|endBody()]]必须在body部分末尾调用触发 [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]] 事件并输出针对 body 结束位置的占位符见 framework/web/View.php。布局中的数据访问布局内有两个预定义变量$this同普通视图一样指向视图组件与$content内容视图的渲染结果。若需访问其他数据请使用访问数据一节中的拉方式若需把内容视图的数据传给布局请使用视图间共享数据一节的方法。使用布局在控制器中通过 [[yii\base\Controller::render()|render()]] 渲染视图时默认应用布局app/views/layouts/main.php。可以通过配置 [[yii\base\Application::layout]]作用于所有控制器或 [[yii\base\Controller::layout]]对单个控制器覆盖前者使用不同布局。例如下面的代码让post控制器渲染视图时使用app/views/layouts/post.php其他未设置layout属性的控制器仍使用默认的main.phpnamespace app\controllers; use yii\web\Controller; class PostController extends Controller { public $layout post; // ... }对于属于模块的控制器还可以配置模块的 [[yii\base\Module::layout|layout]] 属性来为这些控制器指定布局。由于layout属性可以在不同层级控制器、模块、应用配置Yii 在幕后分两步确定某个控制器实际使用的布局文件完整逻辑见 framework/base/Controller.php 的findLayoutFile()第一步确定 layout 值与上下文模块。若控制器的 [[yii\base\Controller::layout]] 不为null则使用该值并以控制器的[[yii\base\Controller::module|模块]]作为上下文模块。若控制器的layout为null则向控制器所有祖先模块含应用本身逐级查找找到第一个layout属性不为null的模块使用该模块及其layout值作为上下文模块与布局值若找不到这样的模块则意味着不应用布局。第二步根据 layout 值与上下文模块确定实际布局文件。layout值可以是路径别名如app/views/layouts/main绝对路径如/main以斜杠开头实际布局文件在应用的[[yii\base\Application::layoutPath|布局目录]]下查找默认是app/views/layouts相对路径如main在上下文模块的[[yii\base\Module::layoutPath|布局目录]]下查找默认为模块[[yii\base\Module::basePath|目录]]下的views/layouts布尔值false不应用布局。若layout值不含文件扩展名默认使用.php。嵌套布局有时需要把一个布局嵌套进另一个布局。例如网站不同板块使用不同布局而这些布局共享同一个生成整体 HTML5 页面结构的基础布局。可以通过在子布局中调用 [[yii\base\View::beginContent()|beginContent()]] 与 [[yii\base\View::endContent()|endContent()]] 实现?php $this-beginContent(app/views/layouts/base.php); ? ...子布局内容... ?php $this-endContent(); ?如上所示子布局内容必须包裹在beginContent()与endContent()之间传给beginContent()的参数指定父布局可以是布局文件或路径别名。用这种方法可以嵌套多层布局。使用块Blocks块Block允许在一个位置定义视图内容、在另一个位置显示常与布局配合使用在内容视图中定义块在布局中显示。调用 [[yii\base\View::beginBlock()|beginBlock()]] 与 [[yii\base\View::endBlock()|endBlock()]] 定义块之后可通过$view-blocks[$blockID]访问其中$blockID是定义块时指定的唯一标识blocks属性见 framework/base/View.php。下面的例子演示如何在内容视图中定义块来定制布局的特定部分。首先在内容视图中定义一个或多个块... ?php $this-beginBlock(block1); ? ...块 1 的内容... ?php $this-endBlock(); ? ... ?php $this-beginBlock(block3); ? ...块 3 的内容... ?php $this-endBlock(); ?然后在布局中若块存在则渲染否则显示默认内容... ?php if (isset($this-blocks[block1])): ? ? $this-blocks[block1] ? ?php else: ? ... 块 1 的默认内容 ... ?php endif; ? ... ?php if (isset($this-blocks[block2])): ? ? $this-blocks[block2] ? ?php else: ? ... 块 2 的默认内容 ... ?php endif; ? ... ?php if (isset($this-blocks[block3])): ? ? $this-blocks[block3] ? ?php else: ? ... 块 3 的默认内容 ... ?php endif; ? ...使用视图组件视图组件yii\base\View及其子类提供大量与视图相关的功能。虽然可以创建 [[yii\base\View]] 或其子类的独立实例但大多数情况下使用的是应用的view组件。可以在应用配置中配置该组件[ // ... components [ view [ class app\components\View, ], // ... ], ]视图组件提供的核心能力分别在独立章节有详细介绍主题化Theming开发与更换网站主题。片段缓存缓存 Web 页面中的片段。客户端脚本处理支持 CSS 与 JavaScript 的注册与渲染。资源包Asset Bundle处理支持资源包的注册与渲染。替代模板引擎允许使用 Twig、Smarty 等其他模板引擎通过在 framework/base/View.php 的renderers属性中配置。开发 Web 页面时还经常用到以下小而实用的功能。设置页面标题每个 Web 页面都应有标题。标题标签通常显示在布局中但实践中标题往往在内容视图中确定。为此 [[yii\web\View]] 提供了 [[yii\web\View::title|title]] 属性把标题信息从内容视图传给布局。在每个内容视图中这样设置标题?php $this-title Мій заголовок сторінки; ?然后确保布局的head部分有如下代码title? Html::encode($this-title) ?/title注册 Meta 标签Web 页面通常需要生成各种 meta 标签。与页面标题类似meta 标签出现在head部分且通常在布局中生成。若想在内容视图中指定要生成的 meta 标签可以调用 [[yii\web\View::registerMetaTag()]]实现见 framework/web/View.php?php $this-registerMetaTag([name keywords, content yii, framework, php]); ?上面的代码在视图组件中注册了一个 keywords meta 标签。注册的 meta 标签在布局渲染完成后输出最终生成的 HTML 会插入到布局中调用 [[yii\web\View::head()]] 的位置meta namekeywords contentyii, framework, php注意多次调用registerMetaTag()会注册多个 meta 标签无论这些标签是否相同。若要确保某种类型只保留一个实例可以在调用时用第二个参数指定键key。例如下面的代码注册了两个 description meta 标签但因为键相同只有第二个会被渲染$this-registerMetaTag([name description, content Це мій класний веб-сайт, який створено за допомогою Yii!], description); $this-registerMetaTag([name description, content Цей веб-сайт про смішних єнотів.], description);注册 Link 标签与 meta 标签类似link 标签在很多场景下很有用例如自定义 favicon、指向 RSS 订阅源或把 OpenID 委托给其他服务器。可以通过 [[yii\web\View::registerLinkTag()]]实现见 framework/web/View.php以与 meta 标签相同的方式处理 link 标签。例如在内容视图中注册$this-registerLinkTag([ title Свіжі новини про Yii, rel alternate, type application/rssxml, href https://www.yiiframework.com/rss.xml/, ]);上面的代码会生成link titleСвіжі новини про Yii relalternate typeapplication/rssxml hrefhttps://www.yiiframework.com/rss.xml/与registerMetaTag()一样调用registerLinkTag()时也可以指定键来避免生成重复的同类型 link 标签。视图事件视图组件在渲染过程中会触发多个事件可以响应这些事件向视图注入内容或在渲染结果发送给用户前对其进行处理[[yii\base\View::EVENT_BEFORE_RENDER|EVENT_BEFORE_RENDER]]beforeRender在控制器开始渲染视图文件时触发见 framework/base/View.php。处理器可将 [[yii\base\ViewEvent::isValid]] 设为false以取消渲染。[[yii\base\View::EVENT_AFTER_RENDER|EVENT_AFTER_RENDER]]afterRender在调用 [[yii\base\View::afterRender()]] 完成文件渲染后触发见 framework/base/View.php。处理器可通过 [[yii\base\ViewEvent::output]] 获取渲染结果并修改它以改变输出。[[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]]由布局中的 [[yii\base\View::beginPage()]] 调用触发。[[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]]由布局中的 [[yii\base\View::endPage()]] 调用触发。[[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]]由布局中的 [[yii\web\View::beginBody()]] 调用触发见 framework/web/View.php。[[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]]由布局中的 [[yii\web\View::endBody()]] 调用触发见 framework/web/View.php。例如下面的代码在页面body末尾注入当前日期\Yii::$app-view-on(View::EVENT_END_BODY, function () { echo date(Y-m-d); });渲染静态页面静态页面指主要内容基本不变、无需访问控制器动态数据的 Web 页面。可以简单地把静态页面代码放进视图然后在控制器中这样输出public function actionAbout() { return $this-render(about); }如果网站包含大量静态页面重复编写相似代码会非常繁琐。解决办法是在控制器中引入一个独立动作standalone action——[[yii\web\ViewAction]]类定义见 framework/web/ViewAction.php。例如namespace app\controllers; use yii\web\Controller; class SiteController extends Controller { public function actions() { return [ page [ class yii\web\ViewAction, ], ]; } }此时只要在app/views/site/pages目录下创建名为about的视图即可通过以下 URL 访问http://localhost/index.php?rsite%2Fpageviewabout请求的GET参数view告诉 [[yii\web\ViewAction]] 请求的是哪个视图动作随后在app/views/site/pages目录下查找该视图。可以通过配置 [[yii\web\ViewAction::viewPrefix]]默认值为pages见 framework/web/ViewAction.php来改变查找目录viewParam属性默认view可自定义 GET 参数名defaultView属性默认index指定未提供参数时的默认视图。最佳实践视图负责以终端用户期望的格式呈现模型数据。总的来说视图应主要包含表现层代码如 HTML以及用于遍历、格式化、渲染数据的简单 PHP 代码不应包含执行数据库查询的代码——这类代码应放在模型中应避免直接访问请求数据如$_GET、$_POST——这属于控制器的职责如需请求数据应由控制器推入视图可以读取模型属性但不应修改它们。为了让视图更易于维护避免创建过于复杂或冗余代码过多的视图可以使用以下技巧使用布局表现公共呈现区域如页头、页脚把复杂的视图拆分成多个较小的视图再用前面介绍的渲染方法把小视图组装成大视图创建并使用部件作为视图的构建块创建并使用辅助类Helper在视图中转换和格式化数据。深入阅读控制器 与 模型MVC 中与视图协同的另外两层。主题化为站点设计与更换主题。片段缓存缓存页面片段以提升性能。客户端脚本处理CSS 与 JavaScript 的注册与渲染。资源包前端资源的管理与发布。替代模板引擎在视图中接入 Twig、Smarty 等模板引擎。核心实现源码framework/base/View.php、framework/web/View.php、framework/base/Controller.php、framework/web/ViewAction.php。赞分享后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载相关推荐Yii 2 视图Views完全指南模板创建、渲染机制、布局体系与静态页面实战Yii 2 视图Views完全指南模板创建、渲染机制、布局体系与静态页面实战 视图Views是 Yii 2 MVC 架构中负责呈现的一层它接收控后端Web框架Yii 2 视图Views完全指南模板创建、渲染管线、布局系统与最佳实践Yii 2 视图Views完全指南模板创建、渲染管线、布局系统与最佳实践 视图是 Yii 2 MVC 架构中负责向终端用户呈现数据的一层。本指南以框架官方后端Web框架Yii 2 视图Views完全指南从模板创建到渲染、布局与 View 组件实战Yii 2 视图Views完全指南从模板创建到渲染、布局与 View 组件实战 视图View是 Yii 2 MVC 架构中负责向终端用户呈现数据的一层后端Web框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考