Solução de problemas

Nette não está funcionando, página branca é exibida

  • Tente colocar ini_set('display_errors', '1'); error_reporting(E_ALL); depois de declare(strict_types=1); no arquivo index.php para forçar a exibição de erros
  • Se você ainda vir uma tela branca, provavelmente há um erro na configuração do servidor e você descobrirá o motivo no log do servidor. Para ter certeza, verifique se o PHP está funcionando, tentando imprimir algo usando echo 'test';.
  • Se você vir um erro Server Error: Pedimos desculpas! …, continue com a próxima seção:

Error 500 Server Error: Pedimos desculpas! …

Esta página de erro é exibida pela Nette no modo de produção. Se você estiver vendo em uma máquina de desenvolvimento, mude para o modo de desenvolvimento.

Se a mensagem de erro contiver Tracy is unable to log error, descubra por que os erros não podem ser registrados. Você pode fazer isso, por exemplo, mudando para o modo desenvolvedor e ligando para Tracy\Debugger::log('hello'); após $configurator->enableTracy(...). Tracy lhe dirá por que ele não pode registrar. A causa geralmente é a falta de permissão para escrever para o diretório log/.

Se a frase Tracy is unable to log error não estiver mais na mensagem de erro (não mais), você pode descobrir o motivo do erro no log no diretório log/.

Uma das razões mais comuns é um cache desatualizado. Enquanto a Nette atualiza o cache de forma inteligente e automática no modo de desenvolvimento, no modo de produção ele se concentra em maximizar o desempenho, e limpar o cache após cada modificação de código fica a seu critério. Tente excluir temp/cache.

Erro #[\ReturnTypeWillChange] attribute should be used

Este erro ocorre se você tiver atualizado o PHP para a versão 8.1, mas estiver usando Nette, que não é compatível com ele. Portanto, a solução é atualizar o Nette para uma versão mais recente usando composer update. Nette suporta o PHP 8.1 desde a versão 3.0. Se você estiver usando uma versão mais antiga (você pode descobrir procurando em composer.json), atualize Nette ou fique com o PHP 8.0.

Definição de permissões de diretório

Se você estiver desenvolvendo em macOS ou Linux (ou qualquer outro sistema baseado em Unix), você precisa configurar privilégios de escrita para o servidor web. Assumindo que sua aplicação esteja localizada no diretório padrão /var/www/html (Fedora, CentOS, RHEL)

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

Em alguns sistemas Linux (Fedora, CentOS, …) SELinux pode ser habilitado por padrão. Você pode precisar atualizar as políticas do SELinux, ou definir caminhos dos diretórios temp e log com o contexto correto de segurança do SELinux. Os diretórios temp e log devem ser configurados no contexto httpd_sys_rw_content_t; para o restante da aplicação – principalmente a pasta app – o contexto httpd_sys_content_t será suficiente. Executar no servidor como root:

semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/log(/.*)?'
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/temp(/.*)?'
restorecon -Rv /var/www/html/MY_PROJECT/

Em seguida, o booleano SELinux httpd_can_network_connect_db precisa ser habilitado para permitir que a Nette se conecte ao banco de dados através da rede. Por padrão, ele está desativado. O comando setsebool pode ser usado para realizar esta tarefa, e se a opção -P for especificada, esta configuração será persistente em todas as reinicializações.

setsebool -P httpd_can_network_connect_db on

Como mudar ou remover www Diretório do URL?

O diretório www/ usado nos projetos modelo em Nette é o chamado diretório público ou raiz documental do projeto. É o único diretório cujo conteúdo é acessível ao navegador. E contém o arquivo index.php, o ponto de entrada que inicia uma aplicação web escrita em Nette.

Para executar o aplicativo na hospedagem, é necessário definir a raiz do documento para este diretório na configuração de hospedagem. Ou, se a hospedagem tiver uma pasta pré-fabricada para o diretório público com um nome diferente (por exemplo web, public_html etc.), simplesmente renomeie www/.

A solução ** não é*** para “se livrar” da pasta www/ usando regras no arquivo .htaccess ou no roteador. Se a hospedagem não permitir que você coloque a raiz do documento em um subdiretório (ou seja, criar diretórios um nível acima do diretório público), procure por outro. Caso contrário, você estaria correndo um risco significativo de segurança. Seria como viver em um apartamento onde não se pode fechar a porta da frente e ela está sempre aberta.

Como configurar um servidor para URLs legais?

Apache: extensão mod_rewrite deve ser permitida e configurada em um 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]

Para alterar a configuração do Apache com arquivos .htaccess, a diretiva AllowOverride tem que ser habilitada. Este é o comportamento padrão para o Apache.

nginx: a diretiva try_files deve ser usada na configuração do servidor:

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args is important
}

O bloco location deve ser definido exatamente uma vez para cada caminho do sistema de arquivos no bloco server. Se você já tem um bloco location / em sua configuração, adicione a diretiva try_files ao bloco existente.

Nette gera links com o mesmo protocolo que a página atual está usando. Assim, na página https://foo e vice-versa. Se você estiver atrás de um proxy reverso HTTPS (por exemplo, no Docker), então você precisa configurar um proxy em configuração para que a detecção do protocolo funcione corretamente.

Se você usa o Nginx como um proxy, você precisa ter um redirecionamento configurado desta forma:

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-aplikace:80;  # IP or hostname of the server/container where the application is running
}

Em seguida, você precisa especificar o proxy IP e, se aplicável, a faixa IP de sua rede local onde você administra a infra-estrutura:

http:
	proxy: IP-proxy/IP-range

Uso de caracteres { } em JavaScript

Os caracteres { and } são usados para escrever etiquetas Latte. Tudo (exceto espaço e aspas) seguindo o { character is considered a tag. If you need to print character { (freqüentemente em JavaScript), você pode colocar um espaço (ou outro caractere vazio) logo após {. Com isto você evita interpretá-lo como uma tag.

Se for necessário imprimir estes caracteres em uma situação em que eles seriam interpretados como uma tag, você pode utilizar tags especiais para imprimir estes caracteres – {l} para { and {r} para }.

{is tag}
{ is not tag }
{l}is not tag{r}

Aviso Presenter::getContext() is deprecated

Nette é de longe a primeira estrutura PHP que mudou para injeção de dependência e levou os programadores a usá-la de forma consistente, a começar pelos apresentadores. Se um apresentador precisar de uma dependência, ele a solicitará. Em contraste, a forma como passamos todo o recipiente DI para uma classe e ele puxa as dependências diretamente dele é considerado um antipadrão (é chamado de localizador de serviços). Esta forma era usada em Nette 0.x antes do advento da injeção de dependência, e sua relíquia é o método Presenter::getContext(), há muito marcado como depreciado.

Se você portar uma aplicação Nette muito antiga, você pode descobrir que ela ainda usa este método. Portanto, desde a versão 3.1 de nette/application você encontrará o aviso Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, desde a versão 4.0 você encontrará o erro de que o método não existe.

A solução limpa, naturalmente, é redesenhar a aplicação para passar dependências usando injeção de dependência. Como alternativa, você pode adicionar seu próprio método getContext() ao seu apresentador base e contornar a mensagem:

abstract 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