Solução de Problemas
- O Nette não funciona, uma página em branco é exibida
- Erro 500 Server Error: We're sorry! …
- Erro 404, o roteamento não funciona
- Alterações nos templates ou na configuração não são refletidas
- Como desativar o cache durante o desenvolvimento?
- Erro #[\ReturnTypeWillChange] attribute should be used
- Configurando Permissões de Diretório
- Como alterar ou remover o diretório www da URL?
- Como configurar o servidor para URLs amigáveis?
- Verificando se o .htaccess funciona
- Verificando se o mod_rewrite está habilitado
- Links são gerados sem https:
- Usando os caracteres { } em JavaScript
- Mensagem Presenter::getContext() is deprecated
O Nette não funciona, uma página em branco é exibida
- Tente inserir
ini_set('display_errors', '1'); error_reporting(E_ALL);
no arquivoindex.php
logo apósdeclare(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:
- Na configuração da hospedagem, definir o document-root para este diretório (
www/
). - Se a hospedagem tiver uma pasta pré-preparada (por exemplo,
public_html
), renomeiewww/
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:
- o arquivo
.htaccess
está localizado no diretório document-root (ou seja, ao lado do arquivoindex.php
) - Apache processa arquivos
.htaccess
- mod_rewrite está habilitado
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.
Links são gerados sem https:
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;
}
}