# Visões (Views) ¶

As views fazem parte da arquitetura 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 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 ¶

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
    use yii\helpers\Html;
    use yii\widgets\ActiveForm;

    /* @var $this yii\web\View */
    /* @var $form yii\widgets\ActiveForm */
    /* @var $model app\models\LoginForm */

    $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 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 ou de outros objetos que desencadeiam a renderização da view .

> 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 ¶

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.

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
    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
    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 o resultado filtrado se sua aplicação precisa de alta performance.

### Organizando as Views ¶

Assim como para os controllers e para os models, 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. 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 diretório do módulo.
- Views renderizadas em um widget 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 ¶

Você pode renderizar views em controllers, em widgets 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 ¶

Nos controllers, você pode chamar os seguintes métodos para renderizar as views:

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

Por exemplo,

    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 ¶

Nos widgets, você pode chamar os seguintes métodos do widget para renderizar views:

- render(): renderiza uma view nomeada.
- renderFile(): renderiza uma view a partir de um caminho de arquivo ou a partir de um alias.

Por exemplo,

    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 ¶

Você pode renderizar uma view dentro de outra chamando um dos seguintes métodos fornecidos pelo componente view:

- render(): renderiza uma view nomeada.
- renderAjax(): renderiza uma view nomeada sem qualquer layout e injeta todos os arquivos JS/CSS registrados. É geralmente utilizado em respostas de requisições Web Ajax.
- renderFile(): renderiza uma view a partir de um caminho de arquivo ou a partir de um alias.

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 view:

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

### Renderização em Outros Lugares ¶

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

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

### Views Nomeadas ¶

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 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 diretório da view do módulo 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 contexto e que implemente yii\base\ViewContextInterface, o caminho do arquivo da view será formado por prefixar o 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 ¶

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`.

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

A abordagem pull ativamente obtém os dados do 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`:

    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 ¶

O componente view fornece a propriedade 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):

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

Em seguida, no arquivo layout, que também é uma view, você pode exibir o "rastro de navegação" (breadcrumbs) usando os dados passados pela propriedade params:

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

## Layouts ¶

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 ¶

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 devem ser salvos no diretório `views/layouts` sob o 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
    use yii\helpers\Html;

    /* @var $this yii\web\View */
    /* @var $content string */
    ?>
    <?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.

- beginPage(): Este método deve ser chamado no início do layout. Ele dispara o evento EVENT_BEGIN_PAGE que indica o início de uma página.
- endPage(): Este método deve ser chamado no final do layout. Ele dispara o evento EVENT_END_PAGE que indica o fim de uma página.
- 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.
- beginBody(): Este método deve ser chamado no início da seção `<body>` . Ele dispara o evento 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).
- endBody(): Este método deve ser chamado no final da seção `<body>`. Ele dispara o evento 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 ¶

Dentro de um layout, você tem acesso a duas variáveis predefinidas: `$this` e `$content`. A primeira se refere ao componente 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 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 . 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 .

### Usando Layouts ¶

Conforme descrito na subseção Renderização em Controllers, quando você renderiza uma view chamando o método 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`.

    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 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 módulo do controller será usado como módulo de contexto.
- Se a propriedade 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 layout não for `null`. O módulo encontrado será usado como módulo de contexto e o valor de sua propriedade 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 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 diretório de layouts do módulo de contexto, cujo valor padrão é `views/layouts` sob o 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 ¶

À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 beginContent() e endContent() nos layouts filhos, como no exemplo a seguir:

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

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

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

Como mostrado acima, o conteúdo do layout filho deve ser inserido entre os métodos beginContent() e endContent(). O parâmetro passado para o 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 ¶

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 beginBlock() e 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 $this->beginBlock('bloco1'); ?>

    ...conteúdoo do bloco1...

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

    ...

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

    ... conteúdoo 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 if (isset($this->blocks['bloco1'])): ?>
        <?= $this->blocks['bloco1'] ?>
    <?php else: ?>
        ... conteúdoo padrãoo para o bloco1 ...
    <?php endif; ?>

    ...

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

    ...

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

## Usando Componentes View ¶

Os 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 conforme o exemplo a seguir:

    [
        // ...
        '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: permite que você desenvolva e altere temas para o seu site.
- fragmento de cache: permite que você guarde em cache um fragmento de uma página.
- manipulação de client scripts: permite que você registre e renderize CSS e JavaScript.
- manipulando asset bundle: permite que você registre e renderize recursos estáticos (asset bundles).
- template engines alternativos: permite que você use outros template engines, tais como o Twig e Smarty.

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 ¶

Cada página deve ter um título. Normalmente, a tag `<title>` é exibida em um layout. 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 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
    $this->title = 'Título da Minha Página';
    ?>

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

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

### Registrando os Meta Tags ¶

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
    $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:

    <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.

    $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 ¶

Assim como as 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:

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

O código acima resultará em

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

Assim como no método registerMetaTags(), você também pode especificar uma chave quando chamar o método registerLinkTag() para evitar a criação de tags link repetidas.

## Eventos da 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.

- 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.
- 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.
- EVENT_BEGIN_PAGE: disparado pela chamada do método yii\base\View::beginPage() nos layouts.
- EVENT_END_PAGE: disparado pela chamada do método yii\base\View::endPage() nos layouts.
- EVENT_BEGIN_BODY: disparado pela chamada do método yii\web\View::beginBody() nos layouts.
- 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:

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

## Renderizando Páginas Estáticas ¶

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:

    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) chamando a classe yii\web\ViewAction em um controller. Por exemplo:

    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 ¶

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 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 como blocos de construção das views.
- crie e use as classes helper (auxiliares) para transformar e formatar os dados nas views.