Solução de Problemas

O Nette não funciona, uma página em branco é exibida

  • Tente inserir ini_set('display_errors', '1'); error_reporting(E_ALL); no arquivo index.php logo após declare(strict_types=1);, isso forçará a exibição de erros.
  • Se você ainda vir uma tela em branco, provavelmente há um erro na configuração do servidor e o motivo será revelado no log do servidor. Para ter certeza, verifique se o PHP está funcionando, tentando imprimir algo usando echo 'test';
  • Se você vir o erro Server Error: We're sorry! …, prossiga para a próxima seção:

Erro 500 Server Error: We're sorry! …

Esta página de erro é exibida pelo Nette no modo de produção. Se ela for exibida no seu computador de desenvolvimento, mude para o modo de desenvolvimento e o Tracy será exibido com uma mensagem detalhada.

O motivo do erro sempre pode ser encontrado no log no diretório log/. No entanto, se a mensagem de erro mostrar a frase Tracy is unable to log error, primeiro descubra por que os erros não podem ser registrados. Você pode fazer isso, por exemplo, mudando temporariamente para o modo de desenvolvimento e deixando o Tracy registrar qualquer coisa após sua inicialização:

// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // seu endereço IP
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('hello'); // Registra 'hello'

O Tracy informará por que não pode registrar. A causa pode ser permissões insuficientes para escrever no diretório log/.

Um dos motivos mais comuns para o erro 500 é um cache desatualizado. Enquanto o Nette no modo de desenvolvimento atualiza o cache automaticamente de forma inteligente, no modo de produção ele se concentra em maximizar o desempenho, e limpar o cache após cada modificação no código é sua responsabilidade. Tente excluir temp/cache.

Erro 404, o roteamento não funciona

Quando todas as páginas (exceto a página inicial) retornam um erro 404, parece haver um problema com a configuração do servidor para URLs amigáveis.

Alterações nos templates ou na configuração não são refletidas

“Modifiquei o template ou a configuração, mas o site ainda exibe a versão antiga.” Este comportamento ocorre no modo de produção, que, por motivos de desempenho, não verifica alterações nos arquivos e mantém o cache gerado uma vez.

Para não ter que limpar manualmente o cache no servidor de produção após cada modificação, habilite o modo de desenvolvimento para o seu endereço IP no arquivo Bootstrap.php:

$configurator->setDebugMode('seu.ip.endereco');

Como desativar o cache durante o desenvolvimento?

O Nette é inteligente e você não precisa desativar o cache nele. Durante o desenvolvimento, ele atualiza automaticamente o cache a cada alteração no template ou na configuração do contêiner DI. Além disso, o modo de desenvolvimento é ativado por autodetecção, então geralmente não é necessário configurar nada, ou apenas o endereço IP.

Ao depurar o roteador, recomendamos desativar o cache no navegador, onde podem estar armazenados, por exemplo, redirecionamentos: abra as Ferramentas do Desenvolvedor (Ctrl+Shift+I ou Cmd+Option+I) e no painel Rede (Network), marque a opção para desativar o cache.

Erro #[\ReturnTypeWillChange] attribute should be used

Este erro aparece se você atualizou o PHP para a versão 8.1, mas está usando uma versão do Nette que não é compatível com ela. A solução é, portanto, atualizar o Nette para uma versão mais recente usando composer update. O Nette suporta PHP 8.1 a partir da versão 3.0. Se você estiver usando uma versão mais antiga (verifique no composer.json), atualize o Nette ou permaneça com o PHP 8.0.

Configurando Permissões de Diretório

Se você estiver desenvolvendo no macOS ou Linux (ou qualquer outro sistema baseado em Unix), precisará definir permissões de escrita para o servidor web. Supondo que sua aplicação esteja localizada no diretório padrão /var/www/html (Fedora, CentOS, RHEL).

cd /var/www/html/MEU_PROJETO
chmod -R a+rw temp log

Em alguns sistemas Linux (Fedora, CentOS, …), o SELinux está ativado por padrão. Você precisará ajustar as políticas do SELinux e definir o contexto de segurança correto do SELinux para as pastas temp e log. Para temp e log, definiremos o tipo de contexto httpd_sys_rw_content_t, para o restante da aplicação (e principalmente para a pasta app), httpd_sys_content_t será suficiente. No servidor, execute:

semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html/MEU_PROJETO/log(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html/MEU_PROJETO/temp(/.*)?'
restorecon -Rv /var/www/html/MEU_PROJETO/

Além disso, é necessário habilitar o booleano do SELinux httpd_can_network_connect_db, que está desativado por padrão e permite que o Nette se conecte ao banco de dados pela rede. Usaremos o comando setsebool e a opção -P para tornar a alteração permanente, ou seja, após a reinicialização do servidor, não teremos surpresas desagradáveis:

setsebool -P httpd_can_network_connect_db on

Como alterar ou remover o diretório www da URL?

O diretório www/ usado nos projetos de exemplo do Nette representa o chamado diretório público ou document-root do projeto. É o único diretório cujo conteúdo é acessível pelo navegador. E contém o arquivo index.php, o ponto de entrada que inicia a aplicação web escrita em Nette.

Para colocar a aplicação em funcionamento na hospedagem, é necessário ter o document-root configurado corretamente. Você tem duas opções:

  1. Na configuração da hospedagem, definir o document-root para este diretório (www/).
  2. Se a hospedagem tiver uma pasta pré-preparada (por exemplo, public_html), renomeie www/ para este nome.

Nunca tente resolver a segurança apenas com .htaccess ou roteador, que impediriam o acesso a outras pastas.

Se a hospedagem não permitir definir o document-root para um subdiretório (ou seja, criar diretórios um nível acima do diretório público), procure outra. Caso contrário, você correria um risco de segurança significativo. Seria como morar em um apartamento onde a porta de entrada não pode ser fechada e está sempre aberta.

Como configurar o servidor para URLs amigáveis?

Apache: é necessário habilitar e configurar as regras mod_rewrite no arquivo .htaccess:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]

Se você encontrar problemas, certifique-se de que:

Se você estiver configurando a aplicação em uma subpasta, pode ser necessário descomentar a linha para definir RewriteBase e ajustá-la para a pasta correta.

nginx: é necessário configurar o redirecionamento usando a diretiva try_files dentro do bloco location / na configuração do servidor.

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args É IMPORTANTE!
}

O bloco location para cada caminho do sistema de arquivos pode ocorrer apenas uma vez no bloco server. Se você já tiver location / na configuração, adicione a diretiva try_files a ele.

Verificando se o .htaccess funciona

A maneira mais fácil de testar se o Apache está usando ou ignorando seu arquivo .htaccess, é danificá-lo intencionalmente. Insira a linha Test no início do arquivo e agora, se você atualizar a página no navegador, deverá ver Internal Server Error.

Se você vir este erro, na verdade é bom! Significa que o Apache está analisando o arquivo .htaccess e encontrou o erro que inserimos lá. Remova a linha Test.

Se Internal Server Error não for exibido, sua configuração do Apache está ignorando o arquivo .htaccess. Geralmente, o Apache o ignora devido à falta da diretiva de configuração AllowOverride All.

Se você estiver hospedando você mesmo, isso pode ser facilmente corrigido. Abra o arquivo httpd.conf ou apache.conf em um editor de texto, localize a seção <Directory> relevante e adicione/altere esta diretiva:

<Directory "/var/www/htdocs"> # caminho para o seu document root
    AllowOverride All
    ...

Se o seu site estiver hospedado em outro lugar, verifique o painel de controle para ver if you can enable the .htaccess file there. If not, contact your hosting provider to do it for you.

Verificando se o mod_rewrite está habilitado

Se você verificou que .htaccess funciona, pode verificar se a extensão mod_rewrite está habilitada. Insira a linha RewriteEngine On no início do arquivo .htaccess e atualize a página no navegador. Se Internal Server Error for exibido, significa que o mod_rewrite não está habilitado. Existem várias maneiras de habilitá-lo. Diferentes maneiras de fazer isso em diferentes configurações podem ser encontradas no Stack Overflow.

O Nette gera links com o mesmo protocolo da própria página. Ou seja, na página https://foo, ele gera links começando com https: e vice-versa. Se você estiver atrás de um servidor proxy reverso que remove HTTPS (por exemplo, no Docker), então é necessário configurar o proxy na configuração para que a detecção de protocolo funcione corretamente.

Se você estiver usando o Nginx como proxy, é necessário ter o redirecionamento configurado, por exemplo, assim:

location / {
	proxy_set_header Host $host;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header X-Forwarded-Port  $server_port;
	proxy_pass http://IP-aplicacao:80;  # IP ou hostname do servidor/contêiner onde a aplicação está rodando
}

Além disso, é necessário indicar na configuração o IP do proxy e, opcionalmente, o intervalo de IP da sua rede local onde você opera a infraestrutura:

http:
	proxy: IP-do-proxy/Intervalo-de-IP

Usando os caracteres { } em JavaScript

Os caracteres { e } são usados para escrever tags Latte. Qualquer coisa que siga o caractere {, exceto um espaço e aspas, é considerada uma tag. Portanto, se você precisar imprimir diretamente o caractere { (frequentemente, por exemplo, em JavaScript), pode colocar um espaço (ou outro caractere em branco) após o caractere {. Isso evitará a tradução como uma tag.

Se for necessário imprimir esses caracteres em uma situação em que o texto seria entendido como uma tag, você pode usar tags especiais para imprimir esses caracteres – {l} para { e {r} para }.

{é uma tag}
{ não é uma tag }
{l}não é uma tag{r}

Mensagem Presenter::getContext() is deprecated

O Nette é de longe o primeiro framework PHP a migrar para a injeção de dependência e a orientar os programadores a usá-la consistentemente, desde os próprios presenters. Se um presenter precisa de alguma dependência, ele solicita-a. Por outro lado, a abordagem em que passamos todo o contêiner DI para a classe, e ela extrai as dependências diretamente dele, é considerada um antipadrão (chamado de service locator). Este método foi usado no Nette 0.x antes da chegada da injeção de dependência, e seu resquício é o método Presenter::getContext(), há muito tempo marcado como obsoleto.

Se você estiver portando uma aplicação Nette muito antiga, pode ser que ela ainda use este método. A partir da versão 3.1 do nette/application, você encontrará o aviso Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, e a partir da versão 4.0, um erro informando que o método não existe.

A solução limpa é, obviamente, refatorar a aplicação para que as dependências sejam passadas usando injeção de dependência. Como uma solução alternativa, você pode adicionar seu próprio método getContext() ao seu presenter base e contornar a mensagem:

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	private Nette\DI\Container $context;

	public function injectContext(Nette\DI\Container $context)
	{
		$this->context = $context;
	}

	public function getContext(): Nette\DI\Container
	{
		return $this->context;
	}
}
versão: 4.0