Visões (Views)
===========

As views fazem parte da arquitetura [MVC](https://pt.wikipedia.org/wiki/MVC).
São a parte do código responsável por apresentar dados aos usuários finais. Em um aplicação Web,
views geralmente são criadas em termos de *view templates* (modelos de view)
 que são arquivos PHP contendo principalmente códigos HTML e
códigos PHP de apresentação.
Os modelos de view são gerenciados pelo [componente da aplicação](structure-application-components.md)
[[yii\web\View|view]] que fornece métodos comumente utilizados para facilitar
a montagem e a renderização da view em si. Para simplificar, geralmente chamamos os modelos de view ou seus arquivos simplesmente
de view.


## Criando Views  <span id="creating-views"></span>

Conforme já mencionado, uma view é simplesmente um arquivo PHP
composto por HTML ou códigos PHP. O código a seguir representa uma view que exibe um formulário
de login. Como você pode ver, o código PHP é utilizado para gerar
as partes de conteúdo dinâmicas, tais como o título da página e o formulário, enquanto o código HTML dispõe os itens na página de uma forma apresentável.

```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>Por favor, preencha os seguintes campos para entrar:</p>

<?php $form = ActiveForm::begin(); ?>
    <?= $form->field($model, 'username') ?>
    <?= $form->field($model, 'password')->passwordInput() ?>
    <?= Html::submitButton('Entrar') ?>
<?php ActiveForm::end(); ?>
```

Em uma view, você pode acessar a variável `$this` que referencia o
[[yii\web\View|componente view]] responsável por gerenciar e renderizar a view
 em questão.

Além de `$this`, pode haver outras variáveis predefinidas na view, tal como
`$model` no exemplo acima. Essas variáveis representam
os dados que foram enviados à view por meio dos
[controllers](structure-controllers.md) ou de outros objetos que
desencadeiam a [renderização da view ](#rendering-views).

> Dica: As variáveis predefinidas são listadas em um bloco de comentário no inicio
  de uma view para que possam ser reconhecidas pelas IDEs. Além de ser também
  uma ótima maneira de documentar suas views.


### Segurança <span id="security"></span>

Ao criar views que geram páginas HTML, é importante que você codifique
e/ou filtre os dados que vêm de usuários antes de exibí-los. Caso contrário,
sua aplicação poderá estar sujeita a um ataque de
[cross-site scripting](https://pt.wikipedia.org/wiki/Cross-site_scripting).

Para exibir um texto simples, codifique-o antes por chamar o método
[[yii\helpers\Html::encode()]]. Por exemplo, o código a seguir codifica o nome do
usuário antes de exibí-lo:

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

<div class="username">
    <?= Html::encode($user->name) ?>
</div>
```

Para exibir conteúdo HTML, use [[yii\helpers\HtmlPurifier]] para
filtrar o conteúdo primeiro. Por exemplo, o código a seguir filtra o conteúdo de `$post->text` antes de exibí-lo:

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

<div class="post">
    <?= HtmlPurifier::process($post->text) ?>
</div>
```

> Dica: Embora o HTMLPurifier faça um excelente trabalho em tornar a saída de dados
  segura, ele não é rápido. Você deveria considerar guardar em [cache](caching-overview.md)
  o resultado filtrado se sua aplicação precisa de alta performance.


### Organizando as Views  <span id="organizing-views"></span>

Assim como para os [controllers](structure-controllers.md) e para os
[models](structure-models.md), existem convenções para organizar as
views.

* Views renderizadas por um controller deveriam ser colocadas sob o diretório `@app/views/IDdoController` por padrão, onde `IDdoController` refere-se ao [ID do controller](structure-controllers.md#routes).
  Por exemplo, se a classe do controller for `PostController`, o diretório
  será `@app/views/post`; se for `PostCommentController`, o diretório será
  `@app/views/post-comment`. Caso o controller pertença a um
  módulo, o diretório seria `views/IDdoController` sob o [[yii\base\Module::basePath|diretório do módulo]].
* Views renderizadas em um [widget](structure-widgets.md) deveriam ser
  colocadas sob o diretório `WidgetPath/views` por padrão, onde `WidgetPath`
  é o diretório o arquivo da classe do widget.
* Para views renderizadas por outros objetos, é recomendado
  que você siga a convenção semelhante à dos widgets.

Você pode personalizar os diretórios padrões das views sobrescrevendo
o método [[yii\base\ViewContextInterface::getViewPath()]] dos controllers ou dos widgets.


## Renderizando Views  <span id="rendering-views"></span>

Você pode renderizar views em
[controllers](structure-controllers.md), em [widgets](structure-widgets.md) ou em qualquer outro lugar chamando os métodos de renderização da view. Esses métodos compartilham uma assinatura similar, como a seguir:

```
/**
 * @param string $view nome da view ou caminho do arquivo, dependendo do método de renderização
 * @param array $params os dados passados para a view
 * @return string resultado da renderização
 */
methodName($view, $params = [])
```


### Renderização em Controllers <span id="rendering-in-controllers"></span>

Nos [controllers](structure-controllers.md), você pode chamar os
seguintes métodos para renderizar as views:

* [[yii\base\Controller::render()|render()]]: renderiza uma [view nomeada](#named-views) e aplica um [layout](#layouts) ao resultado da renderização.
* [[yii\base\Controller::renderPartial()|renderPartial()]]: renderiza
  uma [view nomeada](#named-views) sem qualquer layout.
* [[yii\web\Controller::renderAjax()|renderAjax()]]: renderiza uma [view nomeada](#named-views) sem qualquer layout
  e injeta todos os arquivos JS/CSS registrados. É geralmente utilizado
  em respostas de requisições Web Ajax.
* [[yii\base\Controller::renderFile()|renderFile()]]: renderiza uma view a partir
  de um caminho de arquivo ou a partir de um [alias](concept-aliases.md).
* [[yii\base\Controller::renderContent()|renderContent()]]: renderiza um conteúdo
  estático que será incorporado no [layout](#layouts) selecionado. Este método
  está disponível desde a versão 2.0.1.

Por exemplo,

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

        // renderiza uma view chamada "exibir" e aplica um layout a ela
        return $this->render('exibir', [
            'model' => $model,
        ]);
    }
}
```


### Renderização em Widgets <span id="rendering-in-widgets"></span>

Nos [widgets](structure-widgets.md), você pode chamar os seguintes métodos do
widget para renderizar views:

* [[yii\base\Widget::render()|render()]]: renderiza uma [view nomeada](#named-views).
* [[yii\base\Widget::renderFile()|renderFile()]]: renderiza uma view a partir de
  um caminho de arquivo ou a partir de um [alias](concept-aliases.md).

Por exemplo,

```php
namespace app\components;

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

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

    public function run()
    {
        // renderiza uma view chamada "listar"
        return $this->render('listar', [
            'items' => $this->items,
        ]);
    }
}
```


### Renderização em Views  <span id="rendering-in-views"></span>

Você pode renderizar uma view dentro de outra chamando um dos seguintes
métodos fornecidos pelo [[yii\base\View|componente view]]:

* [[yii\base\Controller::render()|render()]]: renderiza uma [view nomeada](#named-views).
* [[yii\web\Controller::renderAjax()|renderAjax()]]: renderiza uma [view nomeada](#named-views) sem qualquer layout
  e injeta todos os arquivos JS/CSS registrados. É geralmente utilizado
  em respostas de requisições Web Ajax.
* [[yii\base\Controller::renderFile()|renderFile()]]: renderiza uma view a partir
  de um caminho de arquivo ou a partir de um [alias](concept-aliases.md).

Por exemplo, no código a seguir, uma view qualquer renderiza outro arquivo
de view chamado `_visao-geral.php` que encontram-se em seu mesmo diretório.
Lembre-se que `$this` na view referencia o componente [[yii\base\View|view]]:

```php
<?= $this->render('_visao-geral') ?>
```


### Renderização em Outros Lugares <span id="rendering-in-other-places"></span>

Em qualquer lugar, você pode acessar o componente de aplicação [[yii\base\View|view]]
pela expressão `Yii::$app->view` e então chamar qualquer método mencionado anteriormente
para renderizar uma view. Por exemplo,

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


### Views Nomeadas <span id="named-views"></span>

Ao renderizar uma view, você pode especificá-la usando seu nome, ou o caminho do arquivo, ou um alias. Na maioria dos casos,
você usará a primeira maneira por ser mais concisa e flexível. Quando especificamos views por nome, chamamos essas views de *views nomeadas*.

Um nome de view é convertido no caminho de arquivo da view correspondente de
acordo com as seguintes regras:

* Um nome de view pode omitir a extensão do arquivo. Neste caso, o `.php`
  será usado como extensão. Por exemplo, a view chamada `sobre` corresponderá ao
  arquivo `sobre.php`.
* Se o nome da view iniciar com barras duplas `//`, o caminho correspondente
  seria `@app/views/ViewName`. Ou seja, a view será localizada sob o
  [[yii\base\Application::viewPath|diretório das views da aplicação]]. Por exemplo,
  `//site/sobre` corresponderá ao `@app/views/site/sobre.php`.
* Se o nome da view iniciar com uma barra simples `/`, o caminho do arquivo da view
  será formado pelo nome da view com o [[yii\base\Module::viewPath|diretório da view]]
  do [módulo](structure-modules.md) ativo. Se não houver um módulo ativo, o
  `@app/views/ViewName` será usado. Por exemplo, `/usuario/criar` corresponderá
  a `@app/modules/user/views/usuario/criar.php` caso o módulo ativo seja `user`.
  Se não existir um módulo ativo, o caminho do arquivo da view será
  `@app/views/usuario/criar.php`.
* Se a view for renderizada com um [[yii\base\View::context|contexto]] e
  que implemente [[yii\base\ViewContextInterface]], o caminho do arquivo
  da view será formado por prefixar o [[yii\base\ViewContextInterface::getViewPath()|diretório da view]] do contexto ao nome da view.
  Isto se aplica principalmente às views renderizadas em controllers e widgets. Por exemplo,
  `sobre` corresponderá a `@app/views/site/sobre.php` caso o contexto seja o controller
  `SiteController`.
* Se uma view for renderizada dentro de outra, o diretório que contém esta
  outra view será usado para formar o caminho de seu arquivo.
  Por exemplo, `item` corresponderá a `@app/views/post/item.php` se ela for
  renderizada dentro da view `@app/views/post/index.php`.

De acordo com as regras acima, chamar `$this->render('exibir')` em um controller `app\controllers\PostController` vai realmente renderizar o arquivo de view
 `@app/views/post/exibir.php` e, chamar `$this->render('_visaogeral')` nessa view (`exibir.php`) vai renderizar o arquivo de visão `@app/views/post/_visaogeral.php`.


### Acessando Dados em Views  <span id="accessing-data-in-views"></span>

Existem duas abordagens para acessar dados em uma view : *push* e *pull*.

Ao passar os dados como o segundo parâmetro nos métodos de renderização de view, você estará usando a abordagem *push*.
Os dados devem ser representados por um array com pares de nome-valor. Quando a
view estiver sendo renderizada, a função `extract()` do PHP será executada sobre essa array a fim de extrair seus dados em variáveis na view.
Por exemplo, o renderização da view a seguir, em um controller, disponibilizará (pela
abordagem *push*) duas variáveis para a view  `relatorio`: `$foo = 1` e `$bar = 2`.

```php
echo $this->render('relatorio', [
    'foo' => 1,
    'bar' => 2,
]);
```

A abordagem *pull* ativamente obtém os dados do
[[yii\base\View|componente view]] ou de outros objetos acessíveis nas views
(por exemplo, `Yii::$app`). Usando o código a seguir como exemplo, dentro da view você pode acessar seu objeto controller usando a expressão `$this->context`.
E como resultado, será possível acessar quaisquer propriedades ou
métodos do controller, como o seu ID, na view `relatorio`:

```php
O ID do controller é: <?= $this->context->id ?>
?>
```

A abordagem *push* normalmente é a forma preferida de acessar dados nas views
por que as torna menos dependentes de objetos de contexto. A
desvantagem é que você precisa montar manualmente os dados em um array o tempo
todo, o que poderia se tornar tedioso e propenso a erros se uma view for
compartilhada e renderizada em lugares diferentes.


### Compartilhando Dados entre as Views  <span id="sharing-data-among-views"></span>

O [[yii\base\View|componente view]] fornece a propriedade
[[yii\base\View::params|params]] que você pode usar para compartilhar dados entre
as views.

Por exemplo, em uma view `sobre`, você pode ter o seguinte código que especifica
o seguimento atual do "rastro de navegação" (breadcrumbs):

```php
$this->params['breadcrumbs'][] = 'Sobre nós';
```

Em seguida, no arquivo [layout](#layouts), que também é uma view, você pode
exibir o "rastro de navegação" (breadcrumbs) usando os dados passados pela
propriedade [[yii\base\View::params|params]]:

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


## Layouts <span id="layouts"></span>

Layouts são um tipo especial de view que representam as partes comuns
de múltiplas views. Por exemplo, as páginas da maioria das aplicações Web
compartilham o mesmo cabeçalho e rodapé. Embora você possa repetir o mesmo
cabeçalho e rodapé em todas as view, a melhor maneira é fazer isso apenas uma vez
no layout e incorporar o resultado da renderização de uma view em um lugar
apropriado no layout.


### Criando Layouts <span id="creating-layouts"></span>

Visto que os layouts também são views, eles podem ser criados de
forma semelhante às views normais. Por padrão, layouts são salvos
no diretório `@app/views/layouts`. Layouts usados em um
[módulo](structure-modules.md) devem ser salvos no diretório `views/layouts`
sob o [[yii\base\Module::basePath|diretório do módulo]].
Você pode personalizar o diretório padrão de layouts configurando a propriedade
[[yii\base\Module::layoutPath]] da aplicação ou do módulo.

O exemplo a seguir mostra como é um layout. Observe que, para fins ilustrativos,
simplificamos bastante o código do layout. Na prática, você pode querer adicionar mais conteúdos a ele, tais
como tags no head, menu principal, etc.

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

/**
 * @var \yii\web\View $this
 * @var string $content
 */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <?= Html::csrfMetaTags() ?>
    <title><?= Html::encode($this->title) ?></title>
    <?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
    <header>Minha Empresa</header>
    <?= $content ?>
    <footer>&copy; 2014 por Minhas Empresa</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>
```

Conforme pode ver, o layout gera as tags HTML que são comuns a todas as páginas. Na
seçao `<body>`, o layout vai inserir a variável `$content` que representa o
resultado da renderização do conteúdo das views e é enviado ao layout
quando método [[yii\base\Controller::render()]] for chamado.

A maioria dos layouts devem chamar os métodos listados a seguir, conforme ocorreu no código acima. Estes métodos essencialmente desencadeiam eventos referentes ao processo
de renderização para que scripts e tags registrados em outros lugares possam ser
inseridos nos locais onde eles (os métodos) forem chamados.

- [[yii\base\View::beginPage()|beginPage()]]: Este método deve ser chamado no início
  do layout. Ele dispara o evento [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]]
  que indica o início de uma página.
- [[yii\base\View::endPage()|endPage()]]: Este método deve ser chamado no final
  do layout. Ele dispara o evento [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]]
  que indica o fim de uma página.
- [[yii\web\View::head()|head()]]: Este método deve ser chamado na seção `<head>`
  de uma página HTML. Ele gera um marcador que será substituído por código HTML (por exemplo, tags `<link>` e `<meta>`) quando a página termina a renderização.
- [[yii\web\View::beginBody()|beginBody()]]: Este método deve ser chamado no início
  da seção `<body>` . Ele dispara o evento [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]] e gera um marcador que será substituído por código HTML que estiver registrado para essa posição (por exemplo, algum código JavaScript).
- [[yii\web\View::endBody()|endBody()]]: Este método deve ser chamado no final da
  seção `<body>`. Ele dispara o evento [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]]
  e gera um marcador que será substituído por código HTML que estiver registrado para essa posição (por exemplo, algum código JavaScript).


### Acessando Dados nos Layouts <span id="accessing-data-in-layouts"></span>

Dentro de um layout, você tem acesso a duas variáveis predefinidas: `$this` e
`$content`. A primeira se refere ao componente [[yii\base\View|view]] como em views normais, enquanto a segunda contém o resultado da renderização do conteúdo
de uma view que é gerada por chamar o método [[yii\base\Controller::render()|render()]]
no controller.

Se você quiser acessar outros dados nos layouts, você terá de usar a abordagem
*pull* conforme descrito na subseção
[Acessando Dados em Views ](#accessing-data-in-views). Se você quiser
passar os dados do conteúdo da view para um layout, poderá usar o método descrito
na subseção [Compartilhando Dados entre as Views ](#sharing-data-among-views).


### Usando Layouts <span id="using-layouts"></span>

Conforme descrito na subseção [Renderização em Controllers](#rendering-in-controllers),
quando você renderiza uma view chamando o método [[yii\base\Controller::render()|render()]]
em um controller, será aplicado um layout ao resultado da renderização. Por padrão, o layout `@app/views/layouts/main.php` será usado.

Você pode usar um layout diferente configurando ou a propriedade
[[yii\base\Application::layout]] ou a [[yii\base\Controller::layout]].
A primeira especifica o layout usado por todos os controllers,
enquanto a segunda é usada para controllers de forma individual, sobrescrevendo a primeira.
Por exemplo, o código a seguir faz com que o controller `post` usar o
`@app/views/layouts/post.php` como layout quando renderizar as suas views.
Outros controllers, assumindo que a propriedade `layout` da
aplicação não tenha sido alterada, usarão o layout padrão `@app/views/layouts/main.php`.

```php
namespace app\controllers;

use yii\web\Controller;

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

    // ...
}
```

Para os controllers que pertencem a um módulo, você também pode configurar
a propriedade [[yii\base\Module::layout|layout]] do módulo para usar um layout em
particular para esses controllers.

Visto que a propriedade `layout` pode ser configurada em diferentes níveis
(controllers, módulos, aplicação), por trás das cortinas o Yii determina, em duas
etapas, qual arquivo de layout será usado por um controller em particular.

Na primeira etapa, o Yii determina o valor da propriedade do layout e o módulo de contexto:

- Se a propriedade [[yii\base\Controller::layout]] do controller
  não for `null`, ela será usada e o [[yii\base\Controller::module|módulo]]
  do controller será usado como módulo de contexto.
- Se a propriedade [[yii\base\Controller::layout|layout]] for `null`, o Yii pesquisará
  através de todos os módulos ancestrais do
  controller (incluindo a própria aplicação) até encontrar o primeiro módulo cuja propriedade
  [[yii\base\Module::layout|layout]] não for `null`. O módulo encontrado será
  usado como módulo de contexto e o valor de sua propriedade [[yii\base\Module::layout|layout]]
  como o layout escolhido. Se nenhum módulo for encontrado, nenhum
  layout será aplicado.

Na segunda etapa, o Yii determina o real arquivo de layout de acordo com o valor da propriedade layout e com o modulo de contexto obtidos na primeira etapa. O valor da propriedade layout pode ser:

- uma alias de caminho (por exemplo, `@app/views/layouts/main`).
- um caminho absoluto (por exemplo, `/main`): o valor começa com uma
  barra. O arquivo de layout será procurado sob o
  [[yii\base\Application::layoutPath|diretório de layouts]] da aplicação, cujo valor padrão é `@app/views/layouts`.
- um caminho relativo (por exemplo, `main`): o arquivo de layout será procurado
  sob o [[yii\base\Module::layoutPath|diretório de layouts]] do módulo de contexto,
  cujo valor padrão é `views/layouts` sob o [[yii\base\Module::basePath|diretório do módulo]].
- um valor booleano `false`: nenhum layout será aplicado.

Se o valor da propriedade layout não tiver uma extensão de arquivo, será usada a extensão `.php` por padrão.


### Layouts Aninhados <span id="nested-layouts"></span>

Às vezes, você pode querer que um layout seja usado dentro de outro. Por
exemplo, em diferentes seções de um site, você pode querer usar diferentes layouts, e todos esses layouts compartilharão o mesmo layout básico a fim de produzir
toda a estrutura da página HTML. Você pode fazer isso por chamar
os métodos [[yii\base\View::beginContent()|beginContent()]] e
[[yii\base\View::endContent()|endContent()]] nos layouts filhos, como no
exemplo a seguir:

```php
<?php $this->beginContent('@app/views/layouts/base.php'); ?>

...conteúdo do layout filho aqui...

<?php $this->endContent(); ?>
```

Como mostrado acima, o conteúdo do layout filho deve ser inserido entre os métodos [[yii\base\View::beginContent()|beginContent()]] e
[[yii\base\View::endContent()|endContent()]]. O parâmetro passado para o
[[yii\base\View::beginContent()|beginContent()]] indica qual é o layout pai. Ele
pode ser um arquivo de layout ou mesmo um alias.

Usando a abordagem acima, você pode aninhar os layouts em mais de um nível.


### Usando Blocos <span id="using-blocks"></span>

Blocos permitem que você especifique o conteúdo da view em um local e o exiba
em outro. Geralmente são usados em conjunto com os layouts. Por exemplo, você pode
definir um bloco no conteúdo de uma view e exibi-lo no layout.

Para definir um bloco, chame os métodos [[yii\base\View::beginBlock()|beginBlock()]]
e [[yii\base\View::endBlock()|endBlock()]].
O bloco pode então ser acessado via `$view->blocks[$blockID]`, onde o `$blockID` é o
identificador único que você associou ao bloco quando o definiu.

O exemplo a seguir mostra como você pode usar blocos para personalizar as partes
especificas de um layout pelo conteúdo da view.

Primeiramente, no conteúdo da view, defina um ou vários blocos:

```php
...

<?php $this->beginBlock('bloco1'); ?>

...conteúdo do bloco1...

<?php $this->endBlock(); ?>

...

<?php $this->beginBlock('bloco3'); ?>

... conteúdo do bloco3...

<?php $this->endBlock(); ?>
```

Em seguida, no layout, renderize os blocos se estiverem disponíveis
ou exiba um conteúdo padrão se não estiverem.

```php
...
<?php if (isset($this->blocks['bloco1'])): ?>
    <?= $this->blocks['bloco1'] ?>
<?php else: ?>
    ... conteúdo padrão para o bloco1 ...
<?php endif; ?>

...

<?php if (isset($this->blocks['bloco2'])): ?>
    <?= $this->blocks['bloco2'] ?>
<?php else: ?>
    ... conteúdo padrão para o bloco2 ...
<?php endif; ?>

...

<?php if (isset($this->blocks['bloco3'])): ?>
    <?= $this->blocks['bloco3'] ?>
<?php else: ?>
    ... conteúdo padrão para o bloco3 ...
<?php endif; ?>
...
```


## Usando Componentes View  <span id="using-view-components"></span>

Os [[yii\base\View|componentes view]] fornecem muitos recursos. Embora você possa obtê-los por criar instancias individuais de [[yii\base\View]]
ou de suas classes filhas, na maioria dos casos você usará o
componente `view` da aplicação. Você pode configurar este componente nas
[configurações da aplicação](structure-applications.md#application-configurations)
conforme o exemplo a seguir:

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

Componentes de view fornecem úteis recursos relacionados. Cada um deles está descrito com mais detalhes em seções separadas:

* [temas](output-theming.md): permite que você desenvolva e altere temas para
  o seu site.
* [fragmento de cache](caching-fragment.md): permite que você guarde em cache um
  fragmento de uma página.
* [manipulação de client scripts](output-client-scripts.md): permite que você registre e renderize CSS e JavaScript.
* [manipulando asset bundle](structure-assets.md): permite que você registre e renderize [recursos estáticos (asset bundles)](structure-assets.md).
* [template engines alternativos](tutorial-template-engines.md): permite que você use outros template engines, tais como o [Twig](https://twig.symfony.com/)
  e [Smarty](https://www.smarty.net/).

Você também pode usar os seguintes recursos que, embora simples, são úteis quando estiver desenvolvendo suas páginas.


### Configurando Títulos de Página <span id="setting-page-titles"></span>

Cada página deve ter um título. Normalmente, a tag `<title>` é exibida em um [layout](#layouts). Mas, na prática, o título é muitas vezes determinado
no conteúdo das views, em vez de nos layouts. Para resolver este
problema, a classe [[yii\web\View]] fornece a propriedade [[yii\web\View::title|title]] para você passar o título a partir das views para o layout.

Para fazer uso deste recurso, em cada view, você pode definir o título da
página conforme o exemplo a seguir:

```php
<?php
$this->title = 'Título da Minha Página';
?>
```

E, no layout, certifique-se de ter o seguinte código dentro da seção `<head>`:

```php
<title><?= Html::encode($this->title) ?></title>
```


### Registrando os Meta Tags <span id="registering-meta-tags"></span>

Páginas Web geralmente precisam gerar variadas meta tags necessárias a
diversas finalidades. Assim como os títulos, as meta tags precisam estar na seção
`<head>` e normalmente são geradas nos layouts.

Se você quiser especificar quais meta tags gerar no conteúdo das views, poderá chamar o método [[yii\web\View::registerMetaTag()]]
na view, conforme o exemplo a seguir:

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

O código acima registrará uma meta tag "keywords" com o componente view.
A meta tag registrada será renderizadas depois de o layout finalizar sua renderização. O código HTML a seguir será gerado e inserido no local onde você chama [[yii\web\View::head()]] no layout:

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

Observe que se você chamar o método [[yii\web\View::registerMetaTag()]] muitas vezes, ele registrará diversas meta tags, independente se forem as mesmas ou não.

Para garantir que exista apenas uma única instância de um tipo de meta tag,
você pode especificar uma chave no segundo parâmetro ao chamar o método.
Por exemplo, o código a seguir registra dois meta tags "description". No entanto,
apenas o segundo será renderizado.

```php
$this->registerMetaTag(['name' => 'description', 'content' => 'Este é o meu website feito com Yii!'], 'descricao');
$this->registerMetaTag(['name' => 'description', 'content' => 'Este website é sobre coisas divertidas.'], 'descricao');
```


### Registrando Tags Link <span id="registering-link-tags"></span>

Assim como as [meta tags](#registering-meta-tags), as tags link são úteis em muitos
casos, tais como a personalização do favicon, apontamento para feed RSS ou delegação do OpenID para outros servidores.
Você pode trabalhar com as tags link de forma similar às meta tags, usando o método [[yii\web\View::registerLinkTag()]]. Por
exemplo, na view, você pode registrar uma tag link como segue:

```php
$this->registerLinkTag([
    'title' => 'Notícias sobre o Yii',
    'rel' => 'alternate',
    'type' => 'application/rss+xml',
    'href' => 'https://www.yiiframework.com/rss.xml/',
]);
```

O código acima resultará em

```html
<link title="Notícias sobre o Yii" rel="alternate" type="application/rss+xml" href="https://www.yiiframework.com/rss.xml/">
```

Assim como no método [[yii\web\View::registerMetaTag()|registerMetaTags()]],
você também pode especificar uma chave quando chamar o método
[[yii\web\View::registerLinkTag()|registerLinkTag()]] para evitar a criação de
tags link repetidas.


## Eventos da View  <span id="view-events"></span>

[[yii\base\View|Componentes view]] disparam vários eventos durante
o processo de renderização da view. Você pode usar estes eventos para
inserir conteúdo nas views ou processar os resultados da renderização
antes de serem enviados para os usuários finais.

- [[yii\base\View::EVENT_BEFORE_RENDER|EVENT_BEFORE_RENDER]]: disparado no
  início da renderização de um arquivo em um controller. Funções registradas para esse evento (handlers) podem
  definir a propriedade [[yii\base\ViewEvent::isValid]] como `false` para
  cancelar o processo de renderização.
- [[yii\base\View::EVENT_AFTER_RENDER|EVENT_AFTER_RENDER]]: disparado depois
  da renderização de um arquivo pela chamada de [[yii\base\View::afterRender()]].
  Funções registradas para esse evento (handlers) podem capturar o resultado da renderização por meio da propriedade
  [[yii\base\ViewEvent::output]] e podem modificá-lo para alterar o resultado final.
- [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]]: disparado pela chamada
  do método [[yii\base\View::beginPage()]] nos layouts.
- [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]]: disparado pela chamada do
  método [[yii\base\View::endPage()]] nos layouts.
- [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]]: disparado pela chamada
  do método [[yii\web\View::beginBody()]] nos layouts.
- [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]]: disparado pela chamada do
  método [[yii\web\View::endBody()]] nos layouts.

Por exemplo, o código a seguir insere a data atual no final do corpo da página:

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


## Renderizando Páginas Estáticas <span id="rendering-static-pages"></span>

Páginas estáticas referem-se a páginas cujo principal conteúdo é, na maior parte,
estático, sem a necessidade de acessar dados dinâmicos provenientes dos controllers.

Você pode retornar páginas estáticas por colocar seu código na view e então, em um controller, usar o código a seguir:

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

Se o site contiver muitas páginas estáticas, seria tedioso repetir
os códigos similares muitas vezes.
Para resolver este problema, você pode inserir uma
[action "externa" (standalone action)](structure-controllers.md#standalone-actions) chamando a classe
[[yii\web\ViewAction]] em um controller. Por exemplo:

```php
namespace app\controllers;

use yii\web\Controller;

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

Agora, se você criar uma view chamada `sobre` no diretório
`@app/views/site/pages`, poderá exibir por meio da
seguinte URL:

```
http://localhost/index.php?r=site/page&view=sobre
```

O parâmetro `view` passado via `GET` informa à classe [[yii\web\ViewAction]]
qual view foi solicitada. A action, então, irá procurar essa view informada
dentro do diretório `@app/views/site/pages`. Você pode configurar a propriedade
[[yii\web\ViewAction::viewPrefix]] para alterar o diretório onde as views
serão procuradas.


## Boas Práticas <span id="best-practices"></span>

Views são responsáveis por apresentar models (modelos) no formato que os
usuários finais desejam. Em geral, views:

* devem conter principalmente código de apresentação, tal como o HTML, e trechos
  simples de PHP para percorrer, formatar e renderizar dados.
* não devem conter código de consulta ao banco de dados. Consultas assim devem ser feitas nos models.
* devem evitar acessar diretamente os dados da requisição, tais como `$_GET` e
  `$_POST` pois essa tarefa cabe aos controllers.
  Se os dados da requisição forem necessários, deverão ser fornecidos às views
  pelos controllers.
* podem ler as propriedades dos models, mas não devem alterá-las.

Para tornar as views mais gerenciáveis, evite criar views muito complexas
ou que contenham muito código redundante. Você pode usar as seguintes técnicas
para atingir este objetivo:

* use [layouts](#layouts) para representar as seções de apresentação comuns
  (por exemplo, cabeçalho e rodapé).
* divida uma view complicada em varias outras menores. As views
  menores podem ser renderizadas e montadas em uma maior usando os métodos descritos anteriormente.
* crie e use [widgets](structure-widgets.md) como blocos de construção das views.
* crie e use as classes helper (auxiliares) para transformar e formatar os dados nas views.
