Views e layouts
Resolução de templates, layouts, sections, parciais e escape de saída.
Localização
Templates residem em resources/views/. A notação por pontos converte-se em diretórios: home.index aponta para resources/views/home/index.php. Layouts ficam em resources/views/layouts/.
Renderizar pelo controller
$this->view('posts.show', ['post' => $post], 'main');
$this->viewOnly('emails.preview', ['subject' => $subject]);Em view(), null seleciona layout padrão; false ou string vazia força renderização sem layout. Se um layout especificado não existe, tenta o padrão e, na falta deste, renderiza sem layout.
Framework\Support\View
APIs públicas: render()/capture() retornam HTML; make() envia HTML com layout opcional; partial() e partialOnce() incluem parciais; exists() verifica template. Sections: start($name), end(), section($name,$default=''), hasSection(), content(), title(), resetSections().
Escape e CSRF
Use e($value) para escapar conteúdo interpolado. A renderização do Controller injeta automaticamente csrf_field() em formulários com método diferente de GET sem campo _csrf_token; GET e formulários sem atributo method são ignorados. Escape continua necessário: injeção de token não escapa conteúdo da view.
url() forma uma URL da aplicação e asset() prefixa assets/.Básico · renderizar uma View a partir da action
O Controller real de autenticação entrega título e escolhe o layout de login. O nome por pontos é resolvido em resources/views/auth/login.php; cada chave do array fica disponível como variável local da View.
$this->view('auth.login', ['title' => 'Entrar'], 'auth');No layout, o projeto usa View::title() e View::content() para exibir título e conteúdo. `Controller::view()` aceita layout null (padrão), um layout nominal com fallback ao padrão ou false/string vazia para não usar layout. Já `View::make()` tem default `main`; não confunda os dois defaults.
Intermediário · sections e componentes
Sections são úteis quando a filha fornece CSS/JS ou áreas nomeadas ao layout. `start()` abre um buffer; `end()` fecha a section mais recente. `partial()` imprime sempre; `partialOnce()` imprime a View nomeada no máximo uma vez até a reinicialização das sections.
<?php \Framework\Support\View::partial('components.alerts'); ?>O layout pode imprimir `View::section("styles")` e `View::content($content ?? "")`. Os componentes continuam sendo PHP executável; forneça nomes de View constantes no código, não derivados de texto arbitrário do usuário.
Saída segura e decisão de escape
Escape no momento de renderizar reduz XSS contextual. Não escape a mesma string duas vezes nem trate a sanitização de Request como substituta da codificação HTML; saída em atributos/HTML deve usar `e()` conforme o contexto. O helper de View não sanitiza automaticamente qualquer variável.
<?php \Framework\Support\View::partial('components.alerts'); ?>Para reaproveitar mensagens de validação e campos anteriores, veja Sessões/CSRF e Helpers de View.
Contextos reais de templates e componentes
As Views do projeto são arquivos PHP incluídos pelo renderer, não uma linguagem de template separada. Os dados locais variam conforme o arquivo passado a View::render(); não há injeção universal de variáveis em todos os templates.
| Arquivo/contexto | Dados/recursos observados no PHP | Como usar |
|---|---|---|
layouts/main.php | $title, $content, View::title/content/section, asset(), csrf_token(), APP_NAME | O Controller entrega o conteúdo e as sections styles/scripts são renderizadas no layout. |
components/alerts.php | Flash success/error/warning/info e _errors da Session | Agrega mensagens, remove duplicatas e escapa cada mensagem com e(). |
components/pagination.php | Array data com page, last_page, total, from e to; usa $_GET['page'] | Renderize com View::render('components.pagination', ['data' => $result]); preserva outros parâmetros GET. |
auth/*.php | Campos próprios do formulário; csrf_field(), old(), hasError(), error(), url() | Use e() para strings dinâmicas em atributo/texto; alguns templates recebidos imprimem valores de erro/old sem escape, não copie esse padrão. |
layouts/* | title/content/sections names styles e scripts | View::start('styles'), View::end(), View::content($content) e View::section('scripts') compõem a estrutura. |
errors/debug.php | httpCode, httpMessage, exception, context, source e trace | Esse contexto é específico da tela debug e só deve ser exposto com APP_DEBUG efetivamente habilitado. |
errors/404.php | url() e cspNonce() | cspNonce() retorna CSP_NONCE ou string vazia; o helper não cria um nonce por chamada. |
partial() imprime; render() retorna
Use View::render() quando precisar obter HTML para incluir numa expressão. View::partial() já escreve a saída e retorna void; não envolva a chamada em <?= ... ?>.
<?php \Framework\Support\View::partial('components.alerts'); ?>
View::make() e Controller::view() não têm o mesmo fallback
Framework\Support\View::make(string $view, array $data = [], string|false|null $layout = 'main'): static usa o layout main por padrão; false ou null desliga o wrapper. Não herda o fallback/configuração de layout de Controller::view(). Se o layout padrão não existir, renderizará erro em vez de selecionar outro automaticamente. A classe não injeta todos os dados de CSRF que o helper do Controller injeta.
$view = \Framework\Support\View::make('users.show', ['user' => $user], false);
$html = $view->render();render(): string devolve HTML; partial(string $view, array $data = []): void escreve o partial imediatamente, portanto use <?php \Framework\Support\View::partial(...); ?>, não <?= ... ?> esperando um retorno string. Qualquer saída do partial é impressa.
Namespaces e métodos estáticos
Nos exemplos fora de resources/views, importe Framework\Support\View ou use o nome totalmente qualificado. Um trecho como View::make(...) só funciona quando View já foi importada no arquivo PHP; templates não recebem essa classe por importação implícita.
Balanceamento de seções
Cada View::start(string $name): void deve ter exatamente um View::end(): void. end() sem seção aberta lança RuntimeException; um bloco aberto sem fechamento não compõe a seção esperada.
<?php \Framework\Support\View::start('content'); ?>
<p>Conteúdo da página</p>
<?php \Framework\Support\View::end(); ?>Escaping de old input
O helper old() já devolve conteúdo escapado para HTML. Em um atributo, use value="<?= old('email') ?>"; não envolva de novo em e(), para evitar double escaping. Para valores de fallback ou contextos diferentes, escape conforme o contexto HTML apropriado.