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.
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.
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.
Assim como para os controllers e para os models, existem convenções para organizar as views.
@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.WidgetPath/views
por padrão, onde WidgetPath
é o diretório o arquivo da classe do widget.Você pode personalizar os diretórios padrões das views sobrescrevendo o método yii\base\ViewContextInterface::getViewPath() dos controllers ou dos widgets.
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 = [])
Nos controllers, você pode chamar os seguintes métodos para renderizar as views:
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,
]);
}
}
Nos widgets, você pode chamar os seguintes métodos do widget para renderizar views:
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,
]);
}
}
Você pode renderizar uma view dentro de outra chamando um dos seguintes métodos fornecidos pelo componente view:
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') ?>
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');
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:
.php
será usado como extensão. Por exemplo, a view chamada sobre
corresponderá ao
arquivo sobre.php
.//
, 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
./
, 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
.sobre
corresponderá a @app/views/site/sobre.php
caso o contexto seja o controller
SiteController
.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
.
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.
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 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.
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>© 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.
<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.<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).<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).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 .
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:
null
, ela será usada e o módulo
do controller será usado como módulo de contexto.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:
@app/views/layouts/main
)./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
.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.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.
À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údo 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.
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ú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 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; ?>
...
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:
Você também pode usar os seguintes recursos que, embora simples, são úteis quando estiver desenvolvendo suas páginas.
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>
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');
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' => 'https://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="https://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.
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.
false
para
cancelar o processo de renderização.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');
});
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.
Views são responsáveis por apresentar models (modelos) no formato que os usuários finais desejam. Em geral, views:
$_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.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:
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.