Desafio PHP

Sistema de templates com caminhos seguros

Enunciado

Crie uma função renderizar($template, $dados) que inclui um arquivo de template da pasta templates/ usando __DIR__ para montar o caminho. A função deve usar include para que, se o template não existir, exiba uma mensagem de erro amigável e continue. Os dados devem ser extraídos para variáveis locais antes da inclusão. Crie dois templates: home.php que exibe "Bem-vindo, $nome!" e sobre.php que exibe "Sobre nós". No script principal, chame renderizar('home', ['nome' => 'Carlos']) e renderizar('sobre', []). Depois, tente renderizar um template inexistente e mostre a mensagem de erro. O script deve continuar após o erro.

Requisitos

  • A função renderizar deve usar include com caminho baseado em __DIR__.
  • Os dados devem ser extraídos com extract() antes do include.
  • Deve tratar template inexistente exibindo Template não encontrado: <nome> e continuar.
  • A saída deve conter as três linhas: Bem-vindo, Carlos!, Sobre nós e Template não encontrado: contato.

Código inicial

<?php
// funcoes.php
function renderizar($template, $dados) {
    // Monte o caminho usando __DIR__ . '/templates/' . $template . '.php'
    // Verifique se o arquivo existe; se não, exiba mensagem e retorne
    // Extraia os dados para variáveis
    // Inclua o template
}
?>

<?php
// home.php (dentro de templates/)
// Exiba "Bem-vindo, $nome!"
?>

<?php
// sobre.php (dentro de templates/)
// Exiba "Sobre nós"
?>

<?php
// index.php
require __DIR__ . '/funcoes.php';
renderizar('home', ['nome' => 'Carlos']);
renderizar('sobre', []);
renderizar('contato', []);
?>

Saída esperada

Bem-vindo, Carlos!
Sobre nós
Template não encontrado: contato
Ver dica

Use file_exists() para verificar o arquivo antes de incluir. extract() cria variáveis a partir das chaves do array.

Mostrar solução
<?php
// funcoes.php
function renderizar($template, $dados) {
    // Monta o caminho absoluto para o template
    $caminho = __DIR__ . '/templates/' . $template . '.php';
    
    // Verifica se o arquivo existe
    if (!file_exists($caminho)) {
        echo "Template não encontrado: $template\n";
        return;
    }
    
    // Extrai os dados para variáveis locais
    extract($dados);
    
    // Inclui o template (include permite continuar se algo falhar)
    include $caminho;
}
?>
<?php
// templates/home.php
echo "Bem-vindo, $nome!\n";
?>
<?php
// templates/sobre.php
echo "Sobre nós\n";
?>
<?php
// index.php
require __DIR__ . '/funcoes.php';

renderizar('home', ['nome' => 'Carlos']);
renderizar('sobre', []);
renderizar('contato', []);
?>

Passo a passo

  1. A função renderizar recebe o nome do template (sem extensão) e um array de dados.
  2. Monta o caminho completo usando __DIR__ . '/templates/' . $template . '.php', garantindo que o caminho seja absoluto e independente do diretório atual.
  3. Usa file_exists() para verificar se o arquivo existe. Se não, exibe a mensagem Template não encontrado: <nome> e retorna, evitando erro fatal.
  4. Se existir, usa extract($dados) para transformar as chaves do array em variáveis locais (ex.: $nome).
  5. Inclui o template com include. Como é include, se algo der errado dentro do template, o script continua (embora neste caso não haja erro).
  6. No index.php, inclui funcoes.php com require e chama renderizar três vezes.

Por que funciona

O uso de __DIR__ garante que o caminho para a pasta templates seja sempre correto, independentemente de onde o script for executado. A verificação com file_exists evita que um template inexistente cause um aviso do include. O extract permite que o template acesse os dados como variáveis simples, mantendo o código limpo. O include é adequado porque um template ausente não deve interromper todo o sistema; apenas exibimos uma mensagem amigável.

Erros comuns

  • Não usar __DIR__ e montar o caminho com 'templates/' . $template . '.php': se o script for chamado de outro diretório, o arquivo não será encontrado.
  • Usar require em vez de include dentro da função: se o template não existir, o script seria interrompido, impedindo a mensagem amigável.
  • Esquecer de verificar file_exists antes do include: o PHP emitiria um aviso (Warning) e continuaria, mas a saída ficaria poluída.
  • Não extrair os dados: o template não teria acesso às variáveis, causando erros de variável indefinida.

Outra forma de resolver

Usar require_once para incluir os templates, mas isso não é necessário aqui, pois cada template é incluído uma vez. Também poderia usar um autoloader ou funções de template mais robustas, mas para este exemplo, a abordagem com include e __DIR__ é suficiente.

Saída esperada

Bem-vindo, Carlos!
Sobre nós
Template não encontrado: contato