structure-views.md 27.9 KB
Newer Older
Qiang Xue committed
1 2
Views
=====
Alexander Makarov committed
3

Qiang Xue committed
4 5
> Note: This section is under development.

Qiang Xue committed
6
Views are part of the [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) architecture.
Qiang Xue committed
7 8 9 10 11
They are code responsible for presenting data to end users. In a Web application, views are usually created
in terms of *view templates* which are PHP script files containing mainly HTML code and presentational PHP code.
They are managed by the [[yii\web\View|view]] application component which provides commonly used methods
to facilitate view composition and rendering. For simplicity, we often call view templates or view template files
as views.
Qiang Xue committed
12

Qiang Xue committed
13

Qiang Xue committed
14
## Creating Views
Qiang Xue committed
15

Qiang Xue committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
As aforementioned, a view is simply a PHP script mixed with HTML and PHP code. The following is the view
that presents a login form. As you can see, PHP code is used to generate the dynamic content, such as the
page title and the form, while HTML code organizes them into a presentable HTML page.

```php
<?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 = '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(); ?>
```

Within a view, you can access `$this` which refers to the [[yii\web\View|view component]] managing
and rendering this view template.

Besides `$this`, there may be other predefined variables in a view, such as `$form` and `$model` in the above
example. These variables represent the data that are *pushed* into the view by [controllers](structure-controllers.md)
or other objects whose trigger the [view rendering](#rendering-views).

> Tip: The predefined variables are listed in a comment block at beginning of a view so that they can
  be recognized by IDEs. It is also a good practice to document your views.

TODO: features in creating views


## Organizing Views

Like [controllers](structure-controllers.md) and [models](structure-models.md), there are conventions to organize views.

* For views rendered in a controller, they should be put under the directory `@app/views/ControllerID` by default,
  where `ControllerID` refers to [the ID of the controller](structure-controllers.md#routes). For example, if
  the controller class is `PostController`, the directory would be `@app/views/post`; If the class is `PostCommentController`,
  the directory would be `@app/views/post-comment`. In case the controller belongs to a module, the directory
  would be `views/ControllerID` under the [[yii\base\Module::basePath|module directory]].
* For views rendered in a [widget](structure-widgets.md), they should be put under the `WidgetPath/views` directory by
  default, where `WidgetPath` stands for the directory containing the widget class file.
* For views rendered by other objects, it is recommended that you follow the similar convention as that for widgets.

You may customize these default view directories by overriding the [[yii\base\ViewContextInterface::getViewPath()]]
method of controllers or widgets.


## Rendering Views

You can render views in [controllers](structure-controllers.md), [widgets](structure-widgets.md), or any
other places. There are different view rendering methods provided by different classes. However, they share the
similar method signature as follows,

```
/**
 * @param string $view view name or file path, depending on the actual rendering method
 * @param array $params the parameters to be pushed into the view
 */
methodName($view, $params = [])
```


### Passing Data to Views

As you can see, the first parameter specifies which view to be rendered. We will describe more about it in the
[Named Views](#named-views) subsection. The second parameter specifies what data should be "pushed" into the view
and made accessible there. When the rendering method renders a view, it will "extract" the `$params` array so that each
keyed array element is turned into a variable of the same name in the view. For example, if `$params`
is `['a' => 1, 'b' => 2]`, in the view you will be able to access variable `$a` and `$b` whose values are 1 and 2,
respectively.


### Rendering in Controllers

Within [controllers](structure-controllers.md), you may call the following controller methods to render views.

* [[yii\base\Controller::render()|render()]]: renders a [named view](#named-views) and applies a [layout](#layouts)
  to the rendering result.
* [[yii\base\Controller::renderPartial()|renderPartial()]]: renders a [named view](#named-views) without any layout.
* [[yii\base\Controller::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or
  [alias](concept-aliases.md).

For example,
Qiang Xue committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

```php
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;
        }

Qiang Xue committed
127
        // renders a view named "view" and applies a layout to it
Qiang Xue committed
128 129 130 131 132 133 134 135
        return $this->render('view', [
            'model' => $model,
        ]);
    }
}
```


Qiang Xue committed
136 137 138 139 140 141 142
### Rendering in Widgets

Within [widgets](structure-widgets.md), you may call the following widget methods to render views.

* [[yii\base\Widget::render()|render()]]: renders a [named view](#named-views).
* [[yii\base\Widget::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or
  [alias](concept-aliases.md).
Qiang Xue committed
143

Qiang Xue committed
144
For example,
Qiang Xue committed
145

Qiang Xue committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
```php
namespace app\components;

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

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

    public function run()
    {
        // renders a view named "list"
        return $this->render('list', [
            'items' => $this->items,
        ]);
    }
}
```
Qiang Xue committed
165 166


Qiang Xue committed
167
### Rendering in Other Places
Qiang Xue committed
168

Qiang Xue committed
169
In any place, you can render views by calling the following methods of the [[yii\base\View|view]] application component.
Qiang Xue committed
170

Qiang Xue committed
171 172 173
* [[yii\base\View::render()|render()]]: renders a [named view](#named-views).
* [[yii\base\View::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or
  [alias](concept-aliases.md).
Qiang Xue committed
174

Qiang Xue committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
For example,

```php
// displays the view file "@app/views/site/license.php"
echo \Yii::$app->view->renderFile('@app/views/site/license.php');
```

If you are rendering a view within another view, you can use the following code, because `$this` in a view refers to
the [[yii\base\View|view]] component:

```php
<?= $this->renderFile('@app/views/site/license.php') ?>
```


## Named Views

When you render a view, you can specify the view using either a view name or a view file path/alias. In most cases,
you would use the former because it is more concise and flexible. We call views specified using names as *named views*.

A view name is resolved into the corresponding view file path according to the following rules:

* A view name may omit the file extension name. In this case, `.php` will be used as the extension. For example,
  the view name `about` corresponds to the file name `about.php`.
* If the view name starts with double slashes `//`, the corresponding view file path would be `@app/views/ViewName`.
  That is, the view is looked for under the [[yii\base\Application::viewPath|application's view path]].
  For example, `//site/about` will be resolved into `@app/views/site/about.php`.
Qiang Xue committed
202 203 204
* If the view name starts with a single slash `/`, the view file path is formed by prefixing the view name
  with the [[yii\base\Module::viewPath|view path]] of the currently active [module](structure-modules.md).
  If there is no active module, `@app/views/ViewName` will be used. For example, `/user/create` will be resolved into
Qiang Xue committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
  `@app/modules/user/views/user/create.php`, if the currently active module is `user`. If there is no active module,
  the view file path would be `@app/views/user/create.php`.
* If the view is rendered with a [[yii\base\View::context|context]] and the context implements [[yii\base\ViewContextInterface]],
  the view file path is formed by prefixing the [[yii\base\ViewContextInterface::getViewPath()|view path]] of the
  context to the view name. This mainly applies to the views rendered within controllers and widgets. For example,
  `site/about` will be resolved into `@app/views/site/about.php` if the context is the controller `SiteController`.
* If a view is rendered within another view, the directory containing the other view file will be prefixed to
  the new view name to form the actual view file path. For example, `item` will be resolved into `@app/views/post/item`
  if it is being rendered in the view `@app/views/post/index.php`.

According to the above rules, the following code in a controller is actually rendering the view file
`@app/views/post/view.php`

```php
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;
        }

        // renders a view named "view" and applies a layout to it
        return $this->render('view', [
            'model' => $model,
        ]);
    }
}
```

And the following code in the view `@app/views/post/view.php` is actually rendering the view file
`@app/views/post/overview.php`:

```php
<?= $this->render('overview', ['model' => $model]) ?>
```
Qiang Xue committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268


## Layouts

### Nested Layouts


## View Components

## Creating Views

### Setting page title
### Adding meta tags
### Registering link tags
### Registering CSS
### Registering scripts
### Static Pages
### Assets

## Alternative Template Engines
Qiang Xue committed
269

Alexander Makarov committed
270 271 272 273

Basics
------

274 275 276 277
By default, Yii uses PHP in view templates to generate content and elements. A web application view typically contains
some combination of HTML, along with PHP `echo`, `foreach`, `if`, and other basic constructs.
Using complex PHP code in views is considered to be bad practice. When complex logic and functionality is needed,
such code should either be moved to a controller or a widget.
Alexander Makarov committed
278

279
The view is typically called from controller action using the [[yii\base\Controller::render()|render()]] method:
Alexander Makarov committed
280 281 282 283

```php
public function actionIndex()
{
284
    return $this->render('index', ['username' => 'samdark']);
Alexander Makarov committed
285 286 287
}
```

288 289
The first argument to [[yii\base\Controller::render()|render()]] is the name of the view to display.
In the context of the controller, Yii will search for its views in `views/site/` where `site`
Qiang Xue committed
290
is the controller ID. For details on how the view name is resolved, refer to the [[yii\base\Controller::render()]] method.
Alexander Makarov committed
291

292 293 294
The second argument to [[yii\base\Controller::render()|render()]] is a data array of key-value pairs.
Through this array, data can be passed to the view, making the value available in the view as a variable
named the same as the corresponding key.
295 296

The view for the action above would be `views/site/index.php` and can be something like:
Alexander Makarov committed
297 298

```php
299
<p>Hello, <?= $username ?>!</p>
Alexander Makarov committed
300 301
```

302
Any data type can be passed to the view, including arrays or objects.
Alexander Makarov committed
303

304 305 306 307 308 309 310 311 312 313 314
Besides the above [[yii\web\Controller::render()|render()]] method, the [[yii\web\Controller]] class also provides
several other rendering methods. Below is a summary of these methods:

* [[yii\web\Controller::render()|render()]]: renders a view and applies the layout to the rendering result.
  This is most commonly used to render a complete page.
* [[yii\web\Controller::renderPartial()|renderPartial()]]: renders a view without applying any layout.
  This is often used to render a fragment of a page.
* [[yii\web\Controller::renderAjax()|renderAjax()]]: renders a view without applying any layout, and injects all
  registered JS/CSS scripts and files. It is most commonly used to render an HTML output to respond to an AJAX request.
* [[yii\web\Controller::renderFile()|renderFile()]]: renders a view file. This is similar to
  [[yii\web\Controller::renderPartial()|renderPartial()]] except that it takes the file path
Qiang Xue committed
315 316 317
  of the view instead of the view name.


Alexander Makarov committed
318 319 320
Widgets
-------

321 322 323 324 325 326 327 328
Widgets are self-contained building blocks for your views, a way to combine complex logic, display, and functionality into a single component. A widget:

* May contain advanced PHP programming
* Is typically configurable
* Is often provided data to be displayed
* Returns HTML to be shown within the context of the view

There are a good number of widgets bundled with Yii, such as [active form](form.md),
Qiang Xue committed
329
breadcrumbs, menu, and [wrappers around bootstrap component framework](bootstrap-widgets.md). Additionally there are
330
extensions that provide more widgets, such as the official widget for [jQueryUI](http://www.jqueryui.com) components.
331

332
In order to use a widget, your view file would do the following:
333 334 335

```php
// Note that you have to "echo" the result to display it
Alexander Makarov committed
336
echo \yii\widgets\Menu::widget(['items' => $items]);
337 338

// Passing an array to initialize the object properties
Alexander Makarov committed
339
$form = \yii\widgets\ActiveForm::begin([
340 341
    'options' => ['class' => 'form-horizontal'],
    'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],
Alexander Makarov committed
342
]);
343 344 345 346
... form inputs here ...
\yii\widgets\ActiveForm::end();
```

347 348 349
In the first example in the code above, the [[yii\base\Widget::widget()|widget()]] method is used to invoke a widget
that just outputs content. In the second example, [[yii\base\Widget::begin()|begin()]] and [[yii\base\Widget::end()|end()]]
are used for a
350 351 352
widget that wraps content between method calls with its own output. In case of the form this output is the `<form>` tag
with some properties set.

353

Alexander Makarov committed
354 355 356 357 358 359 360
Security
--------

One of the main security principles is to always escape output. If violated it leads to script execution and,
most probably, to cross-site scripting known as XSS leading to leaking of admin passwords, making a user to automatically
perform actions etc.

Qiang Xue committed
361
Yii provides a good tool set in order to help you escape your output. The very basic thing to escape is a text without any
Alexander Makarov committed
362 363 364 365 366 367 368 369
markup. You can deal with it like the following:

```php
<?php
use yii\helpers\Html;
?>

<div class="username">
370
    <?= Html::encode($user->name) ?>
Alexander Makarov committed
371 372 373 374
</div>
```

When you want to render HTML it becomes complex so we're delegating the task to excellent
Qiang Xue committed
375
[HTMLPurifier](http://htmlpurifier.org/) library which is wrapped in Yii as a helper [[yii\helpers\HtmlPurifier]]:
Alexander Makarov committed
376 377 378 379 380 381 382

```php
<?php
use yii\helpers\HtmlPurifier;
?>

<div class="post">
383
    <?= HtmlPurifier::process($post->text) ?>
Alexander Makarov committed
384 385 386 387 388 389 390 391 392
</div>
```

Note that besides HTMLPurifier does excellent job making output safe it's not very fast so consider
[caching result](caching.md).

Alternative template languages
------------------------------

393
There are official extensions for [Smarty](http://www.smarty.net/) and [Twig](http://twig.sensiolabs.org/). In order
Alexander Makarov committed
394
to learn more refer to [Using template engines](template.md) section of the guide.
Alexander Makarov committed
395

396 397
Using View object in templates
------------------------------
Alexander Makarov committed
398

399
An instance of [[yii\web\View]] component is available in view templates as `$this` variable. Using it in templates you
400
can do many useful things including setting page title and meta, registering scripts and accessing the context.
Alexander Makarov committed
401 402 403 404 405 406 407 408 409 410 411 412

### Setting page title

A common place to set page title are view templates. Since we can access view object with `$this`, setting a title
becomes as easy as:

```php
$this->title = 'My page title';
```

### Adding meta tags

413
Adding meta tags such as encoding, description, keywords is easy with view object as well:
Alexander Makarov committed
414 415

```php
Alexander Makarov committed
416
$this->registerMetaTag(['encoding' => 'utf-8']);
Alexander Makarov committed
417 418 419 420 421 422 423 424 425 426 427
```

The first argument is an map of `<meta>` tag option names and values. The code above will produce:

```html
<meta encoding="utf-8">
```

Sometimes there's a need to have only a single tag of a type. In this case you need to specify the second argument:

```html
428 429
$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');
Alexander Makarov committed
430 431
```

Aris Karageorgos committed
432
If there are multiple calls with the same value of the second argument (`meta-description` in this case), the latter will
433
override the former and only a single tag will be rendered:
Alexander Makarov committed
434 435

```html
436
<meta name="description" content="This website is about funny raccoons.">
Alexander Makarov committed
437 438 439 440
```

### Registering link tags

441
`<link>` tag is useful in many cases such as customizing favicon, pointing to RSS feed or delegating OpenID to another
Alexander Makarov committed
442 443 444
server. Yii view object has a method to work with these:

```php
Alexander Makarov committed
445
$this->registerLinkTag([
446 447 448 449
    'title' => 'Lives News for Yii Framework',
    'rel' => 'alternate',
    'type' => 'application/rss+xml',
    'href' => 'http://www.yiiframework.com/rss.xml/',
Alexander Makarov committed
450
]);
Alexander Makarov committed
451 452 453 454 455 456 457 458 459 460 461 462
```

The code above will result in

```html
<link title="Lives News for Yii Framework" rel="alternate" type="application/rss+xml" href="http://www.yiiframework.com/rss.xml/" />
```

Same as with meta tags you can specify additional argument to make sure there's only one link of a type registered.

### Registering CSS

463 464
You can register CSS using [[yii\web\View::registerCss()|registerCss()]] or [[yii\web\View::registerCssFile()|registerCssFile()]].
The former registers a block of CSS code while the latter registers an external CSS file. For example,
Alexander Makarov committed
465 466 467 468 469 470 471 472 473 474 475 476 477

```php
$this->registerCss("body { background: #f00; }");
```

The code above will result in adding the following to the head section of the page:

```html
<style>
body { background: #f00; }
</style>
```

Anderson Müller committed
478
If you want to specify additional properties of the style tag, pass an array of name-values to the third argument.
Anderson Müller committed
479
If you need to make sure there's only a single style tag use fourth argument as was mentioned in meta tags description.
Alexander Makarov committed
480 481

```php
Qiang Xue committed
482
$this->registerCssFile("http://example.com/css/themes/black-and-white.css", [BootstrapAsset::className()], ['media' => 'print'], 'css-print-theme');
Alexander Makarov committed
483 484
```

Qiang Xue committed
485 486 487
The code above will add a link to CSS file to the head section of the page.

* The first argument specifies the CSS file to be registered.
488 489 490
* The second argument specifies that this CSS file depends on [[yii\bootstrap\BootstrapAsset|BootstrapAsset]], meaning it will be added
  AFTER the CSS files in [[yii\bootstrap\BootstrapAsset|BootstrapAsset]]. Without this dependency specification, the relative order
  between this CSS file and the [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] CSS files would be undefined.
Qiang Xue committed
491 492 493 494 495 496
* The third argument specifies the attributes for the resulting `<link>` tag.
* The last argument specifies an ID identifying this CSS file. If it is not provided, the URL of the CSS file will be
  used instead.


It is highly recommended that you use [asset bundles](assets.md) to register external CSS files rather than
497 498
using [[yii\web\View::registerCssFile()|registerCssFile()]]. Using asset bundles allows you to combine and compress
multiple CSS files, which is desirable for high traffic websites.
Qiang Xue committed
499

Alexander Makarov committed
500 501 502

### Registering scripts

503 504 505 506
With the [[yii\web\View]] object you can register scripts. There are two dedicated methods for it:
[[yii\web\View::registerJs()|registerJs()]] for inline scripts and
[[yii\web\View::registerJsFile()|registerJsFile()]] for external scripts.
Inline scripts are useful for configuration and dynamically generated code.
Alexander Makarov committed
507
The method for adding these can be used as follows:
Alexander Makarov committed
508

Alexander Makarov committed
509
```php
510
$this->registerJs("var options = ".json_encode($options).";", View::POS_END, 'my-options');
Alexander Makarov committed
511 512
```

Qiang Xue committed
513 514
The first argument is the actual JS code we want to insert into the page. The second argument
determines where script should be inserted into the page. Possible values are:
Alexander Makarov committed
515

516 517 518 519 520
- [[yii\web\View::POS_HEAD|View::POS_HEAD]] for head section.
- [[yii\web\View::POS_BEGIN|View::POS_BEGIN]] for right after opening `<body>`.
- [[yii\web\View::POS_END|View::POS_END]] for right before closing `</body>`.
- [[yii\web\View::POS_READY|View::POS_READY]] for executing code on document `ready` event. This will register [[yii\web\JqueryAsset|jQuery]] automatically.
- [[yii\web\View::POS_LOAD|View::POS_LOAD]] for executing code on document `load` event. This will register [[yii\web\JqueryAsset|jQuery]] automatically.
Alexander Makarov committed
521

Qiang Xue committed
522 523
The last argument is a unique script ID that is used to identify code block and replace existing one with the same ID
instead of adding a new one. If you don't provide it, the JS code itself will be used as the ID.
Alexander Makarov committed
524

Qiang Xue committed
525
An external script can be added like the following:
Alexander Makarov committed
526 527

```php
Qiang Xue committed
528
$this->registerJsFile('http://example.com/js/main.js', [JqueryAsset::className()]);
Alexander Makarov committed
529 530
```

531 532
The arguments for [[yii\web\View::registerJsFile()|registerJsFile()]] are similar to those for
[[yii\web\View::registerCssFile()|registerCssFile()]]. In the above example,
Qiang Xue committed
533 534 535 536
we register the `main.js` file with the dependency on `JqueryAsset`. This means the `main.js` file
will be added AFTER `jquery.js`. Without this dependency specification, the relative order between
`main.js` and `jquery.js` would be undefined.

537 538
Like for [[yii\web\View::registerCssFile()|registerCssFile()]], it is also highly recommended that you use
[asset bundles](assets.md) to register external JS files rather than using [[yii\web\View::registerJsFile()|registerJsFile()]].
Qiang Xue committed
539

Alexander Makarov committed
540 541 542 543 544 545 546 547

### Registering asset bundles

As was mentioned earlier it's preferred to use asset bundles instead of using CSS and JavaScript directly. You can get
details on how to define asset bundles in [asset manager](assets.md) section of the guide. As for using already defined
asset bundle, it's very straightforward:

```php
548
\frontend\assets\AppAsset::register($this);
Alexander Makarov committed
549 550 551 552
```

### Layout

Alexander Makarov committed
553 554
A layout is a very convenient way to represent the part of the page that is common for all or at least for most pages
generated by your application. Typically it includes `<head>` section, footer, main menu and alike elements.
Reazul Iqbal committed
555
You can find a fine example of the layout in a [basic application template](apps-basic.md). Here we'll review the very
Alexander Makarov committed
556 557 558 559 560 561
basic one without any widgets or extra markup.

```php
<?php
use yii\helpers\Html;
?>
Алексей committed
562
<?php $this->beginPage() ?>
Alexander Makarov committed
563
<!DOCTYPE html>
564
<html lang="<?= Yii::$app->language ?>">
Alexander Makarov committed
565
<head>
566 567 568
    <meta charset="<?= Yii::$app->charset ?>"/>
    <title><?= Html::encode($this->title) ?></title>
    <?php $this->head() ?>
Alexander Makarov committed
569 570
</head>
<body>
Алексей committed
571
<?php $this->beginBody() ?>
572 573 574
    <div class="container">
        <?= $content ?>
    </div>
575
    <footer class="footer">&copy; 2013 me :)</footer>
Алексей committed
576
<?php $this->endBody() ?>
Alexander Makarov committed
577 578
</body>
</html>
Алексей committed
579
<?php $this->endPage() ?>
Alexander Makarov committed
580 581 582 583 584
```

In the markup above there's some code. First of all, `$content` is a variable that will contain result of views rendered
with controller's `$this->render()` method.

585
We are importing [[yii\helpers\Html|Html]] helper via standard PHP `use` statement. This helper is typically used for almost all views
586 587
where one need to escape outputted data.

588 589 590 591
Several special methods such as [[yii\web\View::beginPage()|beginPage()]]/[[yii\web\View::endPage()|endPage()]],
[[yii\web\View::head()|head()]], [[yii\web\View::beginBody()|beginBody()]]/[[yii\web\View::endBody()|endBody()]]
are triggering page rendering events that are used for registering scripts, links and process page in many other ways.
Always include these in your layout in order for the rendering to work correctly.
Alexander Makarov committed
592

593
By default layout is loaded from `views/layouts/main.php`. You may change it at controller or module level by setting
594
different value to `layout` property.
595 596

In order to pass data from controller to layout, that you may need for breadcrumbs or similar elements, use view component
Alexander Makarov committed
597
params property. In controller it can be set as:
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616

```php
$this->view->params['breadcrumbs'][] = 'Contact';
```

In a view it will be:

```php
$this->params['breadcrumbs'][] = 'Contact';
```

In layout file the value can be used like the following:

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

617 618 619 620 621 622 623 624 625 626 627
You may also wrap the view render result into a layout using [[yii\base\View::beginContent()]], [[yii\base\View::endContent()]].
This approach can be used while applying nested layouts:

```php
<?php $this->beginContent('//layouts/overall') ?>
<div class="content">
    <?= $content ?>
<div>
<?php $this->endContent() ?>
```

Alexander Makarov committed
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
### Partials

Often you need to reuse some HTML markup in many views and often it's too simple to create a full-featured widget for it.
In this case you may use partials.

Partial is a view as well. It resides in one of directories under `views` and by convention is often started with `_`.
For example, we need to render a list of user profiles and, at the same time, display individual profile elsewhere.

First we need to define a partial for user profile in `_profile.php`:

```php
<?php
use yii\helpers\Html;
?>

<div class="profile">
644 645
    <h2><?= Html::encode($username) ?></h2>
    <p><?= Html::encode($tagline) ?></p>
Alexander Makarov committed
646 647 648 649 650 651 652
</div>
```

Then we're using it in `index.php` view where we display a list of users:

```php
<div class="user-index">
653 654 655 656 657 658 659 660
    <?php
    foreach ($users as $user) {
        echo $this->render('_profile', [
            'username' => $user->name,
            'tagline' => $user->tagline,
        ]);
    }
    ?>
Alexander Makarov committed
661 662 663 664 665 666
</div>
```

Same way we can reuse it in another view displaying a single user profile:

```php
Alexander Makarov committed
667
echo $this->render('_profile', [
668 669
    'username' => $user->name,
    'tagline' => $user->tagline,
Alexander Makarov committed
670
]);
Alexander Makarov committed
671 672
```

673 674 675 676 677 678 679 680 681 682 683 684 685 686

When you call `render()` to render a partial in a current view, you may use different formats to refer to the partial.
The most commonly used format is the so-called relative view name which is as shown in the above example.
The partial view file is relative to the directory containing the current view. If the partial is located under
a subdirectory, you should include the subdirectory name in the view name, e.g., `public/_profile`.

You may use path alias to specify a view, too. For example, `@app/views/common/_profile`.

And you may also use the so-called absolute view names, e.g., `/user/_profile`, `//user/_profile`.
An absolute view name starts with a single slashes or double slashes. If it starts with a single slash,
the view file will be looked for under the view path of the currently active module. Otherwise, it will
will be looked for under the application view path.


Alexander Makarov committed
687 688 689 690 691 692 693 694 695 696
### Accessing context

Views are generally used either by controller or by widget. In both cases the object that called view rendering is
available in the view as `$this->context`. For example if we need to print out the current internal request route in a
view rendered by controller we can use the following:

```php
echo $this->context->getRoute();
```

Evgeniy Tkachenko committed
697 698
### Static Pages

699 700
If you need to render static pages you can use class `ViewAction`. It represents an action that displays a view according
to a user-specified parameter.
Evgeniy Tkachenko committed
701

702
Usage of the class is simple. In your controller use the class via `actions` method:
Evgeniy Tkachenko committed
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719

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

    //...
}
```

720 721
Then create `index.php` in `@app/views/site/pages/`:

Evgeniy Tkachenko committed
722 723
```php
//index.php
724
<h1>Hello, I am a static page!</h1>
Evgeniy Tkachenko committed
725 726
```

727
That's it. Now you can try it using `/index.php?r=site/static`.
Evgeniy Tkachenko committed
728 729

By default, the view being displayed is specified via the `view` GET parameter. 
730
If you open `/index.php?r=site/static?&view=about` then `@app/views/site/pages/about.php` view file will be used.
Evgeniy Tkachenko committed
731

732
If not changed or specified via GET defaults are the following:
Evgeniy Tkachenko committed
733

734 735 736 737
- GET parameter name: `view`.
- View file used if parameter is missing: `index.php`.
- Directory where views are stored (`viewPrefix`): `pages`.
- Layout for the page rendered matches the one used in controller.
Evgeniy Tkachenko committed
738

739
For more information see [[yii\web\ViewAction]].
Evgeniy Tkachenko committed
740

Alexander Makarov committed
741 742
### Caching blocks

Alexander Makarov committed
743
To learn about caching of view fragments please refer to [caching](caching.md) section of the guide.
744 745 746 747 748

Customizing View component
--------------------------

Since view is also an application component named `view` you can replace it with your own component that extends
749
from [[yii\base\View]] or [[yii\web\View]]. It can be done via application configuration file such as `config/web.php`:
750 751

```php
Alexander Makarov committed
752
return [
753 754 755 756 757 758 759
    // ...
    'components' => [
        'view' => [
            'class' => 'app\components\View',
        ],
        // ...
    ],
Alexander Makarov committed
760
];
761
```