Visões (Views) =========== As views fazem parte da arquitetura [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). 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 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 title = 'Login'; ?>

title) ?>

Por favor, preencha os seguintes campos para entrar:

field($model, 'username') ?> field($model, 'password')->passwordInput() ?> ``` 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 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](http://en.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
name) ?>
``` 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
text) ?>
``` > 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 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 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 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 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 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 render('_visao-geral') ?> ``` ### Renderização em Outros Lugares 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 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 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 é: 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 [[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 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](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 beginPage() ?> <?= Html::encode($this->title) ?> head() ?> beginBody() ?>
Minha Empresa
endBody() ?> endPage() ?> ``` Conforme pode ver, o layout gera as tags HTML que são comuns a todas as páginas. Na seçao ``, 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 `` de uma página HTML. Ele gera um marcador que será substituído por código HTML (por exemplo, tags `` e ``) 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 `` . 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 ``. 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 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 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 À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 beginContent('@app/views/layouts/base.php'); ?> ...conteúdo do layout filho aqui... 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 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 ... beginBlock('bloco1'); ?> ...conteúdo do bloco1... endBlock(); ?> ... beginBlock('bloco3'); ?> ... conteúdo do bloco3... endBlock(); ?> ``` Em seguida, no layout, renderize os blocos se estiverem disponíveis ou exiba um conteúdo padrão se não estiverem. ```php ... blocks['bloco1'])): ?> blocks['bloco1'] ?> ... conteúdo padrão para o bloco1 ... ... blocks['bloco2'])): ?> blocks['bloco2'] ?> ... conteúdo padrão para o bloco2 ... ... blocks['bloco3'])): ?> blocks['bloco3'] ?> ... conteúdo padrão para o bloco3 ... ... ``` ## Usando Componentes View 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](http://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 Cada página deve ter um título. Normalmente, a tag `` é 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) ?> ``` ### 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 `` 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 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 ``` 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 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 ``` 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 [[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 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 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.