Résolution de problèmes
Nette ne fonctionne pas, une page blanche s'affiche
- Essayez de placer
ini_set('display_errors', '1'); error_reporting(E_ALL);aprèsdeclare(strict_types=1);dans le fichierindex.phppour forcer l'affichage des erreurs. - Si vous voyez toujours un écran blanc, il y a probablement une erreur dans la configuration du serveur et vous en trouverez
la raison dans le journal du serveur. Pour en être sûr, vérifiez que PHP fonctionne tout court en essayant d'afficher quelque
chose avec
echo 'test';. - Si vous voyez l'erreur Server Error: We're sorry! …, continuez avec la section suivante :
Erreur 500 Server Error: We're sorry! …
Cette page d'erreur est affichée par Nette en mode production. Si vous la voyez sur votre machine de développement, passez en mode développement et Tracy affichera un rapport détaillé.
Vous trouverez toujours la raison de l'erreur dans le journal du répertoire log/. Si le message d'erreur contient
cependant la phrase Tracy is unable to log error, déterminez d'abord pourquoi les erreurs ne peuvent pas être
journalisées. Vous pouvez le faire, par exemple, en passant temporairement en mode
développement et en laissant Tracy journaliser quelque chose après son démarrage :
// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // votre adresse IP
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('hello');
Tracy vous dira pourquoi elle ne peut pas journaliser. La cause peut être des permissions insuffisantes pour écrire dans le répertoire
log/.
L'une des causes les plus fréquentes d'une erreur 500 est un cache périmé. Alors que Nette met intelligemment le cache à
jour automatiquement en mode développement, en mode production il vise les performances maximales et c'est à vous de vider le
cache après chaque modification du code. Essayez de supprimer temp/cache.
Erreur 404, le routage ne fonctionne pas
Lorsque toutes les pages (sauf la page d'accueil) renvoient une erreur 404, cela ressemble à un problème de configuration du serveur pour les URL élégantes.
Les changements dans les templates ou la configuration ne sont pas pris en compte
„J'ai modifié le template ou la configuration, mais le site affiche toujours l'ancienne version.“ Ce comportement survient en mode production, qui, pour des raisons de performance, ne vérifie pas les changements de fichiers et conserve le cache généré précédemment.
Pour éviter de vider manuellement le cache sur le serveur de production après chaque modification, activez le mode
développement pour votre adresse IP dans le fichier Bootstrap.php :
$this->configurator->setDebugMode('votre.adresse.ip');
Comment désactiver le cache pendant le développement ?
Nette est malin et vous n'avez pas besoin d'y désactiver la mise en cache. Pendant le développement, il met automatiquement le cache à jour dès qu'un template ou la configuration du conteneur DI change. De plus, le mode développement est activé par détection automatique, il n'y a donc généralement rien à configurer, ou seulement l'adresse IP.
Lors du débogage du routeur, nous recommandons de désactiver le cache du navigateur, où peuvent par exemple être stockées les redirections : ouvrez les outils de développement (Ctrl+Shift+I ou Cmd+Option+I) et, dans le panneau Réseau, cochez la case désactivant le cache.
Erreur
#[\ReturnTypeWillChange] attribute should be used
Cette erreur survient si vous avez mis PHP à niveau vers la version 8.1 mais utilisez une version de Nette qui n'est pas
compatible avec elle. La solution est de mettre Nette à jour vers une version plus récente avec composer update.
Nette prend en charge PHP 8.1 depuis la version 3.0. Si vous utilisez une version plus ancienne (vérifiez votre
composer.json), mettez Nette à niveau ou restez sur PHP 8.0.
Régler les permissions des répertoires
Si vous développez sur macOS ou Linux (ou tout autre système fondé sur Unix), vous devez configurer les droits d'écriture
pour le serveur web. En supposant que votre application se trouve dans le répertoire par défaut /var/www/html
(Fedora, CentOS, RHEL) :
cd /var/www/html/MON_PROJET
chmod -R a+rw temp log
Sur certains systèmes Linux (Fedora, CentOS, …), SELinux peut être activé par défaut. Vous devrez peut-être mettre à
jour les politiques SELinux ou attribuer aux chemins des répertoires temp et log le bon contexte de
sécurité SELinux. Les répertoires temp et log devraient recevoir le contexte
httpd_sys_rw_content_t ; pour le reste de l'application – surtout le dossier app – le contexte
httpd_sys_content_t suffira. Exécutez sur le serveur en tant que root :
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MON_PROJET/log(/.*)?'
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MON_PROJET/temp(/.*)?'
restorecon -Rv /var/www/html/MON_PROJET/
Il faut ensuite activer le booléen SELinux httpd_can_network_connect_db pour permettre à Nette de se connecter
à la base de données par le réseau. Il est désactivé par défaut. La commande setsebool peut servir à cette
tâche et, si l'option -P est indiquée, ce réglage persistera après les redémarrages :
setsebool -P httpd_can_network_connect_db on
Comment changer ou supprimer le répertoire www
de l'URL ?
Le répertoire www/ utilisé dans les projets d'exemple de Nette représente le répertoire public, ou
document-root, du projet. C'est le seul répertoire dont le contenu est accessible au navigateur. Il contient le fichier
index.php, le point d'entrée qui lance l'application web Nette.
Pour faire tourner l'application sur un hébergement, vous devez configurer correctement le document-root. Vous avez deux possibilités :
- Définir le document-root sur ce répertoire dans la configuration de l'hébergement.
- Si l'hébergement dispose d'un dossier préparé (par exemple
public_html), renommerwww/avec ce nom.
N'essayez jamais de sécuriser votre application en vous appuyant seulement sur .htaccess ou sur
des règles de routeur pour empêcher l'accès aux autres dossiers.
Si l'hébergement ne permet pas de définir le document-root sur un sous-répertoire (autrement dit de créer des répertoires un niveau au-dessus du répertoire public), cherchez un autre prestataire. Sinon, vous vous exposeriez à un risque de sécurité important. Ce serait comme habiter un appartement dont la porte d'entrée ne peut pas se fermer et reste toujours grande ouverte.
Comment configurer un serveur pour des URL élégantes ?
Apache : vous devez activer et configurer les règles mod_rewrite dans le fichier .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]
Si vous rencontrez des problèmes, assurez-vous que :
- le fichier
.htaccessse trouve dans le répertoire document-root (c'est-à-dire à côté du fichierindex.php) - Apache traite bien les fichiers
.htaccess - mod_rewrite est activé
Si vous installez l'application dans un sous-dossier, vous devrez peut-être décommenter la ligne du réglage
RewriteBase et l'ajuster au bon dossier.
nginx : la redirection doit être configurée à l'aide de la directive try_files à l'intérieur du bloc
location / de la configuration du serveur.
location / {
try_files $uri $uri/ /index.php$is_args$args; # $is_args$args EST IMPORTANT !
}
Le bloc location ne doit apparaître qu'une seule fois par chemin du système de fichiers au sein du bloc
server. Si vous avez déjà un bloc location / dans votre configuration, ajoutez la directive
try_files dans le bloc existant.
Tester si .htaccess fonctionne
La façon la plus simple de tester si Apache utilise ou ignore votre fichier .htaccess est de le casser
intentionnellement. Placez la ligne Test au début du fichier. Si vous rafraîchissez alors la page dans votre
navigateur, vous devriez voir une Internal Server Error.
Si vous voyez cette erreur, c'est en fait une bonne nouvelle ! Cela signifie qu'Apache analyse le fichier
.htaccess et rencontre l'erreur que nous y avons mise. Supprimez la ligne Test.
Si vous ne voyez pas d'Internal Server Error, votre configuration Apache ignore le fichier .htaccess. En
général, Apache l'ignore parce que la directive de configuration AllowOverride All manque.
Si vous hébergez vous-même, c'est facile à corriger. Ouvrez votre httpd.conf ou apache.conf dans
un éditeur de texte, trouvez la section <Directory> concernée et ajoutez ou modifiez cette directive :
<Directory "/var/www/htdocs"> # chemin de votre document root
AllowOverride All
...
Si votre site est hébergé ailleurs, regardez dans votre panneau de contrôle si vous pouvez y activer .htaccess.
Sinon, contactez votre hébergeur pour qu'il le fasse pour vous.
Tester si mod_rewrite est activé
Si vous avez vérifié que .htaccess fonctionne, vous pouvez
vérifier que l'extension mod_rewrite est activée. Placez la ligne RewriteEngine On au début du fichier
.htaccess et rafraîchissez la page dans votre navigateur. Si vous voyez une Internal Server Error, cela
signifie que mod_rewrite n'est pas activé. Il existe plusieurs façons de l'activer. Voyez Stack Overflow pour les différentes
manières d'y parvenir selon les configurations.
Les liens sont générés sans https:
Nette génère les liens avec le même protocole que celui de la page courante. Sur une page https://foo, il
génère donc des liens commençant par https:, et inversement. Si vous êtes derrière un reverse proxy qui supprime
le HTTPS (par exemple dans Docker), vous devez configurer un proxy dans la
configuration pour que la détection du protocole fonctionne correctement.
Si vous utilisez Nginx comme proxy, vous devez avoir une redirection configurée, par exemple ainsi :
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-application:80; # IP ou nom d'hôte du serveur/conteneur où tourne l'application
}
Vous devez en outre indiquer dans la configuration l'IP du proxy et, éventuellement, la plage d'IP de votre réseau local où vous faites tourner l'infrastructure :
http:
proxy: IP-proxy/plage-IP
Utilisation des caractères { } en JavaScript
Les caractères { et } servent à écrire les balises Latte. Tout ce qui suit le caractère
{ (à l'exception de l'espace et du guillemet) est considéré comme une balise. Si vous avez besoin d'afficher
directement le caractère { (souvent en JavaScript), vous pouvez placer une espace (ou un autre caractère blanc)
juste après {. Cela empêche qu'il soit interprété comme une balise.
S'il faut afficher ces caractères dans une situation où le texte serait interprété comme une balise, vous pouvez utiliser
des balises spéciales pour les afficher : {l} pour { et {r} pour }.
{is a tag}
{ is not a tag }
{l}is not a tag{r}
Erreur
Cannot modify header information - headers already sent
Cette erreur survient lorsque l'application essaie d'envoyer un en-tête HTTP (un cookie, une redirection ou le démarrage d'une session) à un moment où une sortie a déjà été envoyée au navigateur. Les en-têtes doivent toujours précéder le corps de la réponse.
Il y a deux causes possibles : soit la sortie part trop tôt, soit l'en-tête est envoyé trop tard.
La sortie part généralement trop tôt à cause d'une espace ou d'une ligne vide égarée avant <?php, après
le ?> fermant, ou à cause d'un BOM que l'éditeur a inséré au début du fichier sans l'afficher. Ne terminez
donc jamais les fichiers PHP par ?>. Pour découvrir quel endroit a affiché quelque chose en premier, utilisez Tracy\OutputDebugger.
L'en-tête est typiquement envoyé trop tard lors du travail avec une session. Nette démarre la session automatiquement à la
première lecture ou écriture et, si cela n'arrive que pendant le rendu du template, la sortie est déjà en route. Travaillez
donc avec la session au plus tard dans la méthode beforeRender(), dans les composants aussi dans les méthodes
handle<Signal>().
N'essayez pas de résoudre le problème en définissant autoStart: true. Cela démarre
la session pour chaque visiteur, robots compris, et crée inutilement une quantité énorme de fichiers sur le disque. La valeur
par défaut smart ne démarre la session que lorsqu'elle est vraiment nécessaire.
Avertissement
Presenter::getContext() is deprecated
Nette a été de loin le premier framework PHP à passer à l'injection de dépendances et à guider les programmeurs pour
qu'ils l'utilisent systématiquement, en commençant par les presenters. Si un presenter a besoin d'une dépendance, il la demande. À l'inverse, passer tout le conteneur DI à une classe
pour qu'elle en tire directement ses dépendances est considéré comme un anti-pattern (connu sous le nom de service locator).
Cette approche était utilisée dans Nette 0.x, avant l'arrivée de l'injection de dépendances, et la méthode
Presenter::getContext(), marquée obsolète depuis longtemps, est un vestige de cette époque.
Si vous portez une très vieille application Nette, vous découvrirez peut-être qu'elle utilise encore cette méthode. Depuis
la version 3.1 de nette/application, vous rencontrerez l'avertissement
Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection et, depuis la version 4.0, une
erreur indiquant que la méthode n'existe pas.
La solution propre est bien sûr de refactoriser l'application pour passer les dépendances par injection de dépendances.
Comme solution de contournement, vous pouvez ajouter votre propre méthode getContext() à votre presenter de base
pour contourner le message :
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;
}
}