>  기사  >  백엔드 개발  >  PHP Yii Framework_php 기술에서 View의 고급 사용

PHP Yii Framework_php 기술에서 View의 고급 사용

WBOY
WBOY원래의
2016-05-16 19:55:221002검색

이름 보기

뷰를 렌더링할 때 뷰 이름이나 뷰 파일 경로/별명을 지정할 수 있습니다. 대부분의 경우 전자가 간결하고 유연하기 때문에 사용됩니다.

뷰 이름은 다음 규칙에 따라 해당 뷰 파일 경로에 할당될 수 있습니다.

뷰 이름에서 파일 확장자는 생략될 수 있습니다. 이 경우 확장자는 about.php 파일 이름에 해당합니다. 뷰 이름은 이중 슬래시 //로 시작하고 해당 뷰 파일 경로는 @app/views/ViewName입니다. 즉, 뷰 파일은 yiibaseApplication::viewPath 경로 아래에 있습니다. @app/views/site/about.php에 해당합니다.
뷰 이름은 단일 슬래시 /로 시작하고, 뷰 파일 경로는 현재 사용되는 모듈의 yiibaseModule::viewPath로 시작됩니다. 모듈이 없으면 @app/views/ViewName으로 시작됩니다. 모듈은 user, /user/create에 해당합니다. @app/modules/user/views/user/create.php가 됩니다. 모듈에 없으면 /user/create는 @app/views/user/create.php에 해당됩니다. .
yiibaseView::context가 뷰를 렌더링하고 컨텍스트가 yiibaseViewContextInterface를 구현하는 경우 뷰 파일 경로는 컨텍스트의 yiibaseViewContextInterface::getViewPath()로 시작합니다. 이는 주로 컨트롤러 및 위젯에서 뷰를 렌더링하는 데 사용됩니다. SiteController, 사이트 /about은 @app/views/site/about.php에 해당합니다.
뷰가 다른 뷰를 렌더링하는 경우 다른 뷰의 파일이 포함된 디렉터리는 현재 뷰의 파일 경로로 시작됩니다. 예를 들어 @app/views/post/index.php 뷰에서 렌더링된 항목은 @app/views/post/item에 해당합니다.
위의 규칙에 따라 컨트롤러에서 appcontrollersPostController는 $this->render('view')를 호출합니다. 이는 $this->가 호출될 때 실제로 @app/views/post/view.php 보기 파일을 렌더링합니다. 뷰 파일인 render('_overview')는 @app/views/post/_overview.php 뷰 파일을 렌더링합니다.

표시된 데이터에 액세스

뷰에서 데이터에 액세스하는 방법에는 푸시와 풀이라는 두 가지 방법이 있습니다.

푸시 메소드는 뷰 렌더링 메소드의 두 번째 매개변수를 통해 데이터를 전달하는 것입니다. 데이터 형식은 뷰가 렌더링될 때 PHP extract() 메소드를 호출하여 배열을 변환합니다. 뷰에 액세스할 수 있는 변수입니다. 예를 들어, 다음 컨트롤러의 렌더링 뷰 코드는 $foo = 1 및 $bar = 2라는 두 개의 변수를 보고서 뷰에 푸시합니다.

echo $this->render('report', [
  'foo' => 1,
  'bar' => 2,
]);
풀 메소드를 사용하면 뷰가 yiibaseView 뷰 구성 요소 또는 기타 개체(예: Yii::$app)에서 데이터를 적극적으로 얻을 수 있습니다. 뷰에서 $this->context 표현식을 사용하여 컨트롤러 ID를 얻을 수 있습니다. 컨트롤러 ID를 가져오는 다음 코드와 같이 보고서 보기에서 컨트롤러의 속성이나 메서드를 가져올 수 있습니다.

The controller ID is: <&#63;= $this->context->id &#63;>
&#63;>
푸시 방법은 뷰가 컨텍스트 개체에 덜 의존하게 하며 뷰가 데이터를 얻는 데 선호되는 방법입니다. 단점은 배열을 수동으로 구성해야 한다는 것입니다. 이는 다소 번거롭고 렌더링할 때 오류가 발생하기 쉽습니다. 다른 장소.

뷰 간 데이터 공유

yiibaseView 뷰 구성 요소는 다양한 뷰가 데이터를 공유할 수 있도록 yiibaseView::params 매개변수 속성을 제공합니다.

예를 들어 정보 뷰에서 다음 코드를 사용하여 현재 탐색경로의 현재 부분을 지정할 수 있습니다.

$this->params['breadcrumbs'][] = 'About Us';
레이아웃 파일(뷰이기도 함)에서 yiibaseView::params 배열에 추가된 값을 사용하여 디스플레이 이동 경로를 생성할 수 있습니다.

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

레이아웃

레이아웃은 여러 뷰의 공통 부분을 나타내는 특수한 뷰입니다. 예를 들어 대부분의 웹 애플리케이션은 동일한 머리글과 바닥글을 각 뷰에 반복하는 것이 좋습니다. 이러한 공개 보기를 레이아웃에 추가하고, 콘텐츠 보기를 렌더링하고 이를 레이아웃의 적절한 위치에 포함시킵니다.

레이아웃 만들기

레이아웃도 뷰이므로 일반 뷰처럼 생성할 수 있습니다. 레이아웃은 기본적으로 @app/views/layouts 경로에 저장됩니다. yiibaseModule::basePath 모듈 디렉터리에 있는 경로를 사용하면 yiibaseModule::layoutPath를 구성하여 애플리케이션이나 모듈의 기본 레이아웃 경로를 사용자 지정할 수 있습니다.

다음 예는 대략적인 레이아웃입니다. 예를 들어, 실제로는 헤더 태그, 메인 메뉴 등 더 많은 콘텐츠를 추가할 수 있습니다.

<&#63;php
use yii\helpers\Html;

/* @var $this yii\web\View */
/* @var $content string 字符串 */
&#63;>
<&#63;php $this->beginPage() &#63;>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"/>
  <&#63;= Html::csrfMetaTags() &#63;>
  <title><&#63;= Html::encode($this->title) &#63;></title>
  <&#63;php $this->head() &#63;>
</head>
<body>
<&#63;php $this->beginBody() &#63;>
  <header>My Company</header>
  <&#63;= $content &#63;>
  <footer>&copy; 2014 by My Company</footer>
<&#63;php $this->endBody() &#63;>
</body>
</html>
<&#63;php $this->endPage() &#63;>

如上所示,布局生成每个页面通用的HTML标签,在6c04bd5ca3fcae76e30b72ad730ca86d标签中,打印$content变量, $content变量代表当yii\base\Controller::render()控制器渲染方法调用时传递到布局的内容视图渲染结果。

大多数视图应调用上述代码中的如下方法,这些方法触发关于渲染过程的事件, 这样其他地方注册的脚本和标签会添加到这些方法调用的地方。

  • yii\base\View::beginPage(): 该方法应在布局的开始处调用, 它触发表明页面开始的 yii\base\View::EVENT_BEGIN_PAGE 事件。
  • yii\base\View::endPage(): 该方法应在布局的结尾处调用, 它触发表明页面结尾的 yii\base\View::EVENT_END_PAGE 时间。
  • yii\web\View::head(): 该方法应在HTML页面的93f0f5c25f18dab9d176bd4f6de5d30e标签中调用, 它生成一个占位符,在页面渲染结束时会被注册的头部HTML代码(如,link标签, meta标签)替换。
  • yii\web\View::beginBody(): 该方法应在6c04bd5ca3fcae76e30b72ad730ca86d标签的开始处调用, 它触发 yii\web\View::EVENT_BEGIN_BODY 事件并生成一个占位符, 会被注册的HTML代码(如JavaScript)在页面主体开始处替换。
  • yii\web\View::endBody(): 该方法应在6c04bd5ca3fcae76e30b72ad730ca86d标签的结尾处调用, 它触发 yii\web\View::EVENT_END_BODY 事件并生成一个占位符, 会被注册的HTML代码(如JavaScript)在页面主体结尾处替换。

布局中访问数据

在布局中可访问两个预定义变量:$this 和 $content,前者对应和普通视图类似的yii\base\View 视图组件 后者包含调用yii\base\Controller::render()方法渲染内容视图的结果。

如果想在布局中访问其他数据,必须使用视图中访问数据一节介绍的拉取方式, 如果想从内容视图中传递数据到布局,可使用视图间共享数据一节中的方法。

使用布局

如控制器中渲染一节描述,当控制器调用yii\base\Controller::render() 方法渲染视图时,会同时使用布局到渲染结果中,默认会使用@app/views/layouts/main.php布局文件。

可配置yii\base\Application::layout 或 yii\base\Controller::layout 使用其他布局文件, 前者管理所有控制器的布局,后者覆盖前者来控制单个控制器布局。 例如,如下代码使 post 控制器渲染视图时使用 @app/views/layouts/post.php 作为布局文件, 假如layout 属性没改变,控制器默认使用 @app/views/layouts/main.php 作为布局文件。

namespace app\controllers;

use yii\web\Controller;

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

  // ...
}

对于模块中的控制器,可配置模块的 yii\base\Module::layout 属性指定布局文件应用到模块的所有控制器。

由于layout 可在不同层级(控制器、模块,应用)配置,在幕后Yii使用两步来决定控制器实际使用的布局。

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

如果控制器的 yii\base\Controller::layout 属性不为空null,使用它作为布局的值, 控制器的 yii\base\Controller::module模块 作为上下文模块。
如果 yii\base\Controller::layout 为空,从控制器的祖先模块(包括应用) 开始找 第一个yii\base\Module::layout 属性不为空的模块,使用该模块作为上下文模块, 并将它的yii\base\Module::layout 的值作为布局的值, 如果都没有找到,表示不使用布局。
第二步,它决定第一步中布局的值和上下文模块对应到实际的布局文件,布局的值可为:

路径别名 (如 @app/views/layouts/main).
绝对路径 (如 /main): 布局的值以斜杠开始,在应用的[[yii\base\Application::layoutPath|layout path] 布局路径 中查找实际的布局文件,布局路径默认为 @app/views/layouts。
相对路径 (如 main): 在上下文模块的yii\base\Module::layoutPath布局路径中查找实际的布局文件, 布局路径默认为yii\base\Module::basePath模块目录下的views/layouts 目录。
布尔值 false: 不使用布局。
布局的值没有包含文件扩展名,默认使用 .php作为扩展名。

嵌套布局

有时候你想嵌套一个布局到另一个,例如,在Web站点不同地方,想使用不同的布局, 同时这些布局共享相同的生成全局HTML5页面结构的基本布局,可以在子布局中调用 yii\base\View::beginContent() 和yii\base\View::endContent() 方法,如下所示:

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

...child layout content here...

<&#63;php $this->endContent(); &#63;>

如上所示,子布局内容应在 yii\base\View::beginContent() 和 yii\base\View::endContent() 方法之间,传给 yii\base\View::beginContent() 的参数指定父布局,父布局可为布局文件或别名。

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

使用数据块

数据块可以在一个地方指定视图内容在另一个地方显示,通常和布局一起使用, 例如,可在内容视图中定义数据块在布局中显示它。

调用 yii\base\View::beginBlock() 和 yii\base\View::endBlock() 来定义数据块, 使用 $view->blocks[$blockID] 访问该数据块,其中 $blockID 为定义数据块时指定的唯一标识ID。

如下实例显示如何在内容视图中使用数据块让布局使用。

首先,在内容视图中定一个或多个数据块:

...

<&#63;php $this->beginBlock('block1'); &#63;>

...content of block1...

<&#63;php $this->endBlock(); &#63;>

...

<&#63;php $this->beginBlock('block3'); &#63;>

...content of block3...

<&#63;php $this->endBlock(); &#63;>

然后,在布局视图中,数据块可用的话会渲染数据块,如果数据未定义则显示一些默认内容。

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

...

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

...

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

使用视图组件

yii\base\View视图组件提供许多视图相关特性,可创建yii\base\View或它的子类实例来获取视图组件, 大多数情况下主要使用 view应用组件,可在应用配置中配置该组件, 如下所示:

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

视图组件提供如下实用的视图相关特性,每项详情会在独立章节中介绍:

  • 主题: 允许为你的Web站点开发和修改主题;
  • 片段缓存: 允许你在Web页面中缓存片段;
  • 客户脚本处理: 支持CSS 和 JavaScript 注册和渲染;
  • 资源包处理: 支持 资源包的注册和渲染;
  • 模板引擎: 允许你使用其他模板引擎,如 Twig, Smarty。

开发Web页面时,也可能频繁使用以下实用的小特性。

设置页面标题

每个Web页面应有一个标题,正常情况下标题的标签显示在 布局中, 但是实际上标题大多由内容视图而不是布局来决定,为解决这个问题, yii\web\View 提供 yii\web\View::title 标题属性可让标题信息从内容视图传递到布局中。

为利用这个特性,在每个内容视图中设置页面标题,如下所示:

<&#63;php
$this->title = 'My page title';
&#63;>
然后在视图中,确保在 <head> 段中有如下代码:

<title><&#63;= Html::encode($this->title) &#63;></title>

注册Meta元标签

Web页面通常需要生成各种元标签提供给不同的浏览器,如93f0f5c25f18dab9d176bd4f6de5d30e中的页面标题,元标签通常在布局中生成。

如果想在内容视图中生成元标签,可在内容视图中调用yii\web\View::registerMetaTag()方法,如下所示:

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

以上代码会在视图组件中注册一个 "keywords" 元标签,在布局渲染后会渲染该注册的元标签, 然后,如下HTML代码会插入到布局中调用yii\web\View::head()方法处:

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

注意如果多次调用 yii\web\View::registerMetaTag() 方法,它会注册多个元标签,注册时不会检查是否重复。

为确保每种元标签只有一个,可在调用方法时指定键作为第二个参数, 例如,如下代码注册两次 "description" 元标签,但是只会渲染第二个。

$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');

注册链接标签

和 Meta标签 类似,链接标签有时很实用,如自定义网站图标,指定Rss订阅,或授权OpenID到其他服务器。 可以和元标签相似的方式调用yii\web\View::registerLinkTag(),例如,在内容视图中注册链接标签如下所示:

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

上述代码会转换成

复制代码 代码如下:

0c6bd91b444b9de3c6ff536a95babeb4


和 yii\web\View::registerMetaTag() 类似, 调用yii\web\View::registerLinkTag() 指定键来避免生成重复链接标签。

视图事件

yii\base\View 视图组件会在视图渲染过程中触发几个事件, 可以在内容发送给终端用户前,响应这些事件来添加内容到视图中或调整渲染结果。

  • yii\base\View::EVENT_BEFORE_RENDER: 在控制器渲染文件开始时触发, 该事件可设置 yii\base\ViewEvent::isValid 为 false 取消视图渲染。
  • yii\base\View::EVENT_AFTER_RENDER: 在布局中调用 yii\base\View::beginPage() 时触发, 该事件可获取yii\base\ViewEvent::output的渲染结果,可修改该属性来修改渲染结果。
  • yii\base\View::EVENT_BEGIN_PAGE: 在布局调用 yii\base\View::beginPage() 时触发;
  • yii\base\View::EVENT_END_PAGE: 在布局调用 yii\base\View::endPage() 是触发;
  • yii\web\View::EVENT_BEGIN_BODY: 在布局调用 yii\web\View::beginBody() 时触发;
  • yii\web\View::EVENT_END_BODY: 在布局调用 yii\web\View::endBody() 时触发。

例如,如下代码将当前日期添加到页面结尾处:

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

渲染静态页面

静态页面指的是大部分内容为静态的不需要控制器传递动态数据的Web页面。

可将HTML代码放置在视图中,在控制器中使用以下代码输出静态页面:

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

如果Web站点包含很多静态页面,多次重复相似的代码显得很繁琐, 为解决这个问题,可以使用一个在控制器中称为 yii\web\ViewAction 的独立操作。 例如:

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 的视图, 可通过如下rul显示该视图:

http://localhost/index.php?r=site/page&view=about
GET 中 view 参数告知 yii\web\ViewAction 操作请求哪个视图,然后操作在 @app/views/site/pages目录下寻找该视图,可配置 yii\web\ViewAction::viewPrefix 修改搜索视图的目录。

最佳实践

视图负责将模型的数据展示用户想要的格式,总之,视图

  • 应主要包含展示代码,如HTML, 和简单的PHP代码来控制、格式化和渲染数据;
  • 不应包含执行数据查询代码,这种代码放在模型中;
  • 应避免直接访问请求数据,如 $_GET, $_POST,这种应在控制器中执行, 如果需要请求数据,应由控制器推送到视图。
  • 可读取模型属性,但不应修改它们。
  • 为使模型更易于维护,避免创建太复杂或包含太多冗余代码的视图,可遵循以下方法达到这个目标:
  • 使用 布局 来展示公共代码(如,页面头部、尾部);
  • 将复杂的视图分成几个小视图,可使用上面描述的渲染方法将这些小视图渲染并组装成大视图;
  • 创建并使用 小部件 作为视图的数据块;
  • 创建并使用助手类在视图中转换和格式化数据。
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.