Risoluzione dei problemi
- Nette non funziona, viene mostrata una pagina bianca
- Errore 500 Server Error: We're sorry! …
- Errore 404, il routing non funziona
- Le modifiche ai template o alla configurazione non si vedono
- Come disattivare la cache durante lo sviluppo?
- Errore #[\ReturnTypeWillChange] attribute should be used
- Impostazione dei permessi delle directory
- Come cambiare o rimuovere la directory www dall'URL?
- Come configurare il server per gli URL leggibili?
- Verificare che .htaccess funzioni
- Verificare che mod_rewrite sia attivo
- I link vengono generati senza https:
- Uso dei caratteri { } in JavaScript
- Errore Cannot modify header information - headers already sent
- Avviso Presenter::getContext() is deprecated
Nette non funziona, viene mostrata una pagina bianca
- Provate a mettere
ini_set('display_errors', '1'); error_reporting(E_ALL);dopodeclare(strict_types=1);nel fileindex.phpper forzare la visualizzazione degli errori. - Se vedete ancora una schermata bianca, probabilmente c'è un errore nella configurazione del server e il motivo lo troverete
nel log del server. Per sicurezza verificate che PHP funzioni affatto, provando a stampare qualcosa con
echo 'test';. - Se vedete l'errore Server Error: We're sorry! …, proseguite con la sezione successiva:
Errore 500 Server Error: We're sorry! …
Questa pagina di errore viene mostrata da Nette in modalità produzione. Se la vedete sulla vostra macchina di sviluppo, passate alla modalità di sviluppo e Tracy vi mostrerà un report dettagliato.
Il motivo dell'errore lo trovate sempre nel log nella directory log/. Se però nel messaggio di errore compare la
frase Tracy is unable to log error, scoprite prima perché gli errori non si possono registrare. Potete farlo per
esempio passando
temporaneamente alla modalità di sviluppo e lasciando che Tracy registri qualcosa dopo il suo avvio:
// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // il vostro indirizzo IP
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('hello');
Tracy vi dirà perché non può registrare. La causa possono essere i permessi insufficienti per scrivere nella directory
log/.
Uno dei motivi più frequenti dell'errore 500 è una cache obsoleta. Mentre in modalità di sviluppo Nette aggiorna la cache
automaticamente e in modo intelligente, in modalità produzione punta alle massime prestazioni e la cancellazione della cache dopo
ogni modifica del codice è compito vostro. Provate a cancellare temp/cache.
Errore 404, il routing non funziona
Quando tutte le pagine (tranne la homepage) restituiscono l'errore 404, sembra un problema di configurazione del server per gli URL leggibili.
Le modifiche ai template o alla configurazione non si vedono
“Ho modificato il template o la configurazione, ma il sito mostra ancora la vecchia versione.” Questo comportamento si verifica in modalità produzione, che per motivi di prestazioni non controlla le modifiche ai file e mantiene la cache generata in precedenza.
Per non dover cancellare a mano la cache sul server di produzione dopo ogni modifica, attivate la modalità di sviluppo per il
vostro indirizzo IP nel file Bootstrap.php:
$this->configurator->setDebugMode('vostro.indirizzo.ip');
Come disattivare la cache durante lo sviluppo?
Nette è intelligente e non serve disattivarci la cache. Durante lo sviluppo aggiorna automaticamente la cache ogni volta che cambia il template o la configurazione del container DI. La modalità di sviluppo si attiva inoltre per rilevamento automatico, quindi di solito non serve configurare nulla, oppure solo l'indirizzo IP.
Quando fate il debug del router, consigliamo di disattivare la cache del browser, in cui possono per esempio essere salvati i redirect: aprite i Developer Tools (Ctrl+Shift+I oppure Cmd+Option+I) e nel pannello Network spuntate la casella per disattivare la cache.
Errore
#[\ReturnTypeWillChange] attribute should be used
Questo errore compare se avete aggiornato PHP alla versione 8.1 ma usate una versione di Nette che non è compatibile con
essa. La soluzione è aggiornare Nette a una versione più recente con composer update. Nette supporta PHP 8.1 dalla
versione 3.0. Se usate una versione più vecchia (controllate il vostro composer.json), aggiornate Nette oppure restate con PHP 8.0.
Impostazione dei permessi delle directory
Se sviluppate su macOS o Linux (o su un altro sistema basato su Unix), dovete impostare i permessi di scrittura per il
server web. Supponendo che la vostra applicazione si trovi nella directory predefinita /var/www/html (Fedora,
CentOS, RHEL):
cd /var/www/html/MIO_PROGETTO
chmod -R a+rw temp log
Su alcuni sistemi Linux (Fedora, CentOS, …) SELinux può essere attivo per impostazione predefinita. Può essere necessario
aggiornare le policy di SELinux oppure impostare per i percorsi delle directory temp e log il corretto
contesto di sicurezza SELinux. Le directory temp e log andrebbero impostate con il contesto
httpd_sys_rw_content_t; per il resto dell'applicazione, soprattutto per la cartella app, basterà il
contesto httpd_sys_content_t. Eseguite sul server come root:
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MIO_PROGETTO/log(/.*)?'
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MIO_PROGETTO/temp(/.*)?'
restorecon -Rv /var/www/html/MIO_PROGETTO/
Va inoltre attivato il booleano SELinux httpd_can_network_connect_db, che permette a Nette di connettersi al
database in rete. Per impostazione predefinita è disattivato. Per questo compito si può usare il comando setsebool
e, se si indica l'opzione -P, l'impostazione resta valida anche dopo il riavvio:
setsebool -P httpd_can_network_connect_db on
Come cambiare o rimuovere la directory www
dall'URL?
La directory www/ usata nei progetti di esempio di Nette rappresenta la directory pubblica, il document-root del
progetto. È l'unica directory il cui contenuto è accessibile dal browser. Contiene il file index.php, il punto di
ingresso che avvia l'applicazione web Nette.
Per far girare l'applicazione su un hosting, dovete configurare correttamente il document-root. Avete due possibilità:
- Impostare nella configurazione dell'hosting il document-root su questa directory.
- Se l'hosting ha una cartella già pronta (per esempio
public_html), rinominatewww/con questo nome.
Non provate mai a mettere in sicurezza la vostra applicazione usando solo .htaccess o le regole
del router per impedire l'accesso alle altre cartelle.
Se l'hosting non permette di impostare il document-root su una sottodirectory (cioè di creare directory un livello sopra la directory pubblica), cercatevi un altro provider. Altrimenti correreste un notevole rischio di sicurezza. Sarebbe come vivere in un appartamento la cui porta d'ingresso non si può chiudere ed è sempre spalancata.
Come configurare il server per gli URL leggibili?
Apache: dovete attivare e configurare le regole di mod_rewrite nel file .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 incontrate problemi, assicuratevi che:
- il file
.htaccesssi trovi nella directory document-root (cioè accanto al fileindex.php) - Apache elabori i file
.htaccess - mod_rewrite sia attivo
Se installate l'applicazione in una sottocartella, può essere necessario decommentare la riga con l'impostazione
RewriteBase e impostarla sulla cartella corretta.
nginx: il reindirizzamento va configurato con la direttiva try_files dentro il blocco
location / nella configurazione del server.
location / {
try_files $uri $uri/ /index.php$is_args$args; # $is_args$args È IMPORTANTE!
}
Il blocco location deve comparire una sola volta per ogni percorso del filesystem dentro il blocco
server. Se nella vostra configurazione avete già un blocco location /, aggiungete la direttiva
try_files nel blocco esistente.
Verificare che .htaccess funzioni
Il modo più semplice di verificare se Apache usa o ignora il vostro file .htaccess è romperlo di proposito.
Mettete all'inizio del file la riga Test. Se ora aggiornate la pagina nel browser, dovreste vedere un Internal
Server Error.
Se vedete questo errore, è in realtà una buona cosa! Significa che Apache analizza il file .htaccess e incontra
l'errore che ci abbiamo messo. Rimuovete la riga Test.
Se non vedete l'Internal Server Error, la vostra configurazione di Apache ignora il file .htaccess. Di
solito Apache lo ignora perché manca la direttiva di configurazione AllowOverride All.
Se lo ospitate voi stessi, si risolve facilmente. Aprite il vostro httpd.conf oppure apache.conf in
un editor di testo, trovate la sezione <Directory> pertinente e aggiungete o modificate questa direttiva:
<Directory "/var/www/htdocs"> # percorso del vostro document root
AllowOverride All
...
Se il vostro sito è ospitato altrove, controllate nel pannello di controllo se potete attivare lì .htaccess. Se
non è possibile, contattate il vostro provider di hosting perché lo faccia per voi.
Verificare che mod_rewrite sia attivo
Se avete verificato che .htaccess funziona, potete verificare
che l'estensione mod_rewrite sia attiva. Mettete all'inizio del file .htaccess la riga RewriteEngine On
e aggiornate la pagina nel browser. Se vedete un Internal Server Error, significa che mod_rewrite non è attivo. Ci sono
vari modi per attivarlo. Guardate su Stack Overflow i vari modi in cui si può fare nelle diverse configurazioni.
I link vengono generati senza https:
Nette genera i link con lo stesso protocollo della pagina corrente. Su una pagina https://foo genera quindi link
che iniziano con https: e viceversa. Se state dietro a un reverse proxy che rimuove HTTPS (per esempio in Docker),
dovete impostare il proxy nella configurazione perché il
rilevamento del protocollo funzioni correttamente.
Se usate Nginx come proxy, dovete avere il reindirizzamento impostato per esempio così:
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-applicazione:80; # IP o hostname del server/container su cui gira l'applicazione
}
Nella configurazione dovete inoltre indicare l'IP del proxy ed eventualmente l'intervallo di IP della vostra rete locale in cui fate girare l'infrastruttura:
http:
proxy: IP-proxy/intervallo-IP
Uso dei caratteri { } in JavaScript
I caratteri { e } si usano per scrivere i tag di Latte. Tutto ciò che segue il carattere
{ (tranne lo spazio e le virgolette) è considerato un tag. Se dovete stampare direttamente il carattere
{ (spesso in JavaScript), potete mettere uno spazio (o un altro carattere di spaziatura) subito dopo {.
Questo impedisce che venga interpretato come tag.
Se è necessario stampare questi caratteri in una situazione in cui il testo verrebbe interpretato come tag, potete usare
i tag speciali per stampare questi caratteri: {l} per { e {r} per }.
{is a tag}
{ is not a tag }
{l}is not a tag{r}
Errore
Cannot modify header information - headers already sent
Questo errore si verifica quando l'applicazione prova a inviare un header HTTP (un cookie, un redirect o l'avvio di una sessione) in un momento in cui al browser è già stato inviato qualche output. Gli header devono sempre precedere il corpo della risposta.
Le cause possibili sono due: o l'output esce troppo presto, oppure l'header viene inviato troppo tardi.
L'output esce di solito troppo presto a causa di uno spazio sperduto o di una riga vuota prima di <?php, dopo
la chiusura ?>, oppure a causa di un BOM che l'editor ha inserito all'inizio del file e non mostra. Perciò non
terminate mai i file PHP con ?>. Per scoprire quale punto ha stampato per primo, usate Tracy\OutputDebugger.
L'header viene inviato troppo tardi tipicamente quando si lavora con la sessione. Nette avvia la sessione automaticamente alla
prima lettura o scrittura e, se questo avviene solo durante il rendering del template, l'output è già in viaggio. Lavorate
perciò con la sessione al più tardi nel metodo beforeRender(), nei componenti anche nei metodi
handle<Signal>().
Non provate a risolvere il problema impostando autoStart:
true. Questo avvia la sessione per ogni visitatore, robot compresi, e crea inutilmente un'enorme quantità di file sul disco.
Il valore predefinito smart avvia la sessione solo quando serve davvero.
Avviso Presenter::getContext() is deprecated
Nette è stato di gran lunga il primo framework PHP a passare alla dependency injection e a guidare i programmatori a usarla
in modo coerente, a partire proprio dai presenter. Se un presenter ha bisogno di una dipendenza, se la fa passare. Al contrario, passare l'intero
container DI a una classe e lasciare che estragga da sé le dipendenze è considerato un antipattern (noto come service locator).
Questo approccio si usava in Nette 0.x prima dell'avvento della dependency injection e il metodo
Presenter::getContext(), da tempo contrassegnato come deprecato, è un residuo di quell'epoca.
Se state portando avanti un'applicazione Nette molto vecchia, potreste scoprire che usa ancora questo metodo. Dalla versione
3.1 di nette/application incontrerete l'avviso
Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection e dalla versione 4.0 un errore
che dice che il metodo non esiste.
La soluzione pulita è naturalmente rifattorizzare l'applicazione perché passi le dipendenze con la dependency injection. Come
soluzione di ripiego potete aggiungere al vostro presenter di base un vostro metodo getContext() per aggirare il
messaggio:
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
private Nette\DI\Container $context;
public function injectContext(Nette\DI\Container $context): void
{
$this->context = $context;
}
public function getContext(): Nette\DI\Container
{
return $this->context;
}
}