Fehlersuche

Nette funktioniert nicht, es wird eine weiße Seite angezeigt

  • Versuchen Sie, ini_set('display_errors', '1'); error_reporting(E_ALL); nach declare(strict_types=1); in die Datei index.php einzufügen, um die Anzeige von Fehlern zu erzwingen.
  • Wenn Sie immer noch einen weißen Bildschirm sehen, liegt wahrscheinlich ein Fehler in der Serverkonfiguration vor und Sie werden den Grund dafür im Serverprotokoll finden. Um sicherzugehen, überprüfen Sie, ob PHP überhaupt funktioniert, indem Sie versuchen, mit echo 'test'; etwas zu drucken.
  • Wenn Sie eine Fehlermeldung Server Error sehen: Es tut uns leid! …, fahren Sie mit dem nächsten Abschnitt fort:

Fehler 500 Serverfehler: Es tut uns leid! …

Diese Fehlerseite wird von Nette im Produktionsmodus angezeigt. Wenn Sie sie auf Ihrem Entwicklungscomputer sehen, wechseln Sie in den Entwicklermodus und Tracy wird mit einem detaillierten Bericht angezeigt.

Sie können den Grund für den Fehler immer im Verzeichnis log/ finden. Wenn die Fehlermeldung jedoch die Phrase Tracy is unable to log error anzeigt, ermitteln Sie zunächst, warum Fehler nicht protokolliert werden können. Dies können Sie zum Beispiel tun, indem Sie vorübergehend in den Entwicklermodus wechseln und Tracy nach dem Start alles protokollieren lassen:

// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // Ihre IP-Adresse
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('hello');

Tracy wird Ihnen mitteilen, warum es nicht protokollieren kann. Die Ursache könnte eine unzureichende Berechtigung zum Schreiben in das Verzeichnis log/ sein.

Einer der häufigsten Gründe für einen 500-Fehler ist ein veralteter Cache. Während Nette im Entwicklungsmodus den Cache automatisch aktualisiert, konzentriert es sich im Produktionsmodus auf die Maximierung der Leistung, und es liegt an Ihnen, den Cache nach jeder Codeänderung zu löschen. Versuchen Sie, temp/cache zu löschen.

Fehler 404, Routing funktioniert nicht

Wenn alle Seiten (außer der Homepage) einen 404-Fehler zurückgeben, sieht es nach einem Serverkonfigurationsproblem für hübsche URLs aus.

Änderungen an Vorlagen oder der Konfiguration werden nicht berücksichtigt

"Ich habe die Vorlage oder die Konfiguration geändert, aber die Website zeigt immer noch die alte Version an. Dieses Verhalten tritt im Produktionsmodus auf, der aus Leistungsgründen nicht auf Datei-Änderungen prüft und einen zuvor erstellten Cache beibehält.

Um zu vermeiden, dass der Cache auf dem Produktionsserver nach jeder Änderung manuell geleert wird, aktivieren Sie den Entwicklungsmodus für Ihre IP-Adresse in der Datei Bootstrap.php:

$this->configurator->setDebugMode('your.ip.address');

Wie kann man den Cache während der Entwicklung deaktivieren?

Nette ist intelligent, und Sie müssen das Caching nicht deaktivieren. Während der Entwicklung wird der Cache automatisch aktualisiert, sobald eine Änderung in der Vorlage oder der DI-Container-Konfiguration vorgenommen wird. Außerdem wird der Entwicklungsmodus durch automatische Erkennung aktiviert, so dass normalerweise nichts konfiguriert werden muss, auch nicht die IP-Adresse.

Bei der Fehlersuche im Router empfiehlt es sich, den Browser-Cache zu deaktivieren, in dem z. B. Umleitungen gespeichert sein könnten: Öffnen Sie die Entwicklertools (Strg+Umschalt+I oder Cmd+Option+I) und aktivieren Sie im Bereich Netzwerk das Kontrollkästchen zur Deaktivierung des Cache.

Fehler #[\ReturnTypeWillChange] attribute should be used

Dieser Fehler tritt auf, wenn Sie PHP auf Version 8.1 aktualisiert haben, aber Nette verwenden, das damit nicht kompatibel ist. Die Lösung besteht also darin, Nette mit composer update auf eine neuere Version zu aktualisieren. Nette unterstützt PHP 8.1 seit Version 3.0. Wenn Sie eine ältere Version verwenden (Sie können dies unter composer.json herausfinden), aktualisieren Sie Nette oder bleiben Sie bei PHP 8.0.

Verzeichnisberechtigungen einstellen

Wenn Sie auf macOS oder Linux (oder einem anderen Unix-basierten System) entwickeln, müssen Sie Schreibrechte für den Webserver konfigurieren. Angenommen, Ihre Anwendung befindet sich in dem Standardverzeichnis /var/www/html (Fedora, CentOS, RHEL)

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

Auf einigen Linux-Systemen (Fedora, CentOS, …) kann SELinux standardmäßig aktiviert sein. Möglicherweise müssen Sie die SELinux-Richtlinien aktualisieren oder die Pfade der Verzeichnisse temp und log mit dem richtigen SELinux-Sicherheitskontext versehen. Die Verzeichnisse temp und log sollten auf den Kontext httpd_sys_rw_content_t gesetzt werden; für den Rest der Anwendung – hauptsächlich den Ordner app – reicht der Kontext httpd_sys_content_t aus. Führen Sie das Programm auf dem Server als root aus:

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/

Als nächstes muss der SELinux-Boolesche Wert httpd_can_network_connect_db aktiviert werden, damit Nette über das Netzwerk eine Verbindung zur Datenbank herstellen kann. Standardmäßig ist er deaktiviert. Der Befehl setsebool kann zur Durchführung dieser Aufgabe verwendet werden, und wenn die Option -P angegeben wird, bleibt diese Einstellung über Neustarts hinweg bestehen.

setsebool -P httpd_can_network_connect_db on

Wie kann man das Verzeichnis www aus der URL ändern oder entfernen?

Das Verzeichnis www/, das in den Beispielprojekten in Nette verwendet wird, ist das so genannte öffentliche Verzeichnis oder Dokument-Wurzelverzeichnis des Projekts. Es ist das einzige Verzeichnis, dessen Inhalt für den Browser zugänglich ist. Und es enthält die Datei index.php, den Einstiegspunkt, der eine in Nette geschriebene Webanwendung startet.

Um die Anwendung auf dem Hosting laufen zu lassen, müssen Sie das document-root in der Hosting-Konfiguration auf dieses Verzeichnis setzen. Oder, wenn das Hosting einen vorgefertigten Ordner für das öffentliche Verzeichnis mit einem anderen Namen hat (zum Beispiel web, public_html usw.), benennen Sie einfach www/ um.

Die Lösung ist nicht, den Zugriff auf alle Verzeichnisse außer www/ durch Regeln in der Datei .htaccess oder im Router zu verhindern. Wenn Ihr Hosting nicht erlaubt, das Stammverzeichnis für Dokumente auf ein Unterverzeichnis zu setzen (d. h. Verzeichnisse eine Ebene über dem öffentlichen Verzeichnis anzulegen), sollten Sie sich nach einem anderen Hosting-Dienst umsehen. Andernfalls würden Sie sich einem erheblichen Sicherheitsrisiko aussetzen. Das wäre so, als würden Sie in einer Wohnung leben, deren Eingangstür nicht geschlossen werden kann und immer offen steht.

Wie konfiguriert man einen Server für schöne URLs?

Apache: Sie müssen mod_rewrite-Regeln in der Datei .htaccess aktivieren und einstellen:

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]

Wenn Sie auf Probleme stoßen, stellen Sie sicher, dass:

Wenn Sie die Anwendung in einem Unterordner einrichten, müssen Sie möglicherweise die Zeile für die Einstellung RewriteBase auskommentieren und auf den richtigen Ordner setzen.

nginx: Die Richtlinie try_files sollte in der Serverkonfiguration verwendet werden:

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args IST WICHTIG!
}

Der Block location muss genau einmal für jeden Dateisystempfad im Block server definiert werden. Wenn Sie bereits einen location / -Block in Ihrer Konfiguration haben, fügen Sie die Direktive try_files in den bestehenden Block ein.

Testen, ob .htaccess funktioniert

Der einfachste Weg, um zu testen, ob der Apache Ihre .htaccess Datei verwendet oder ignoriert, ist, sie absichtlich zu unterbrechen. Setzen Sie die Zeile Test an den Anfang der Datei. Wenn Sie nun die Seite in Ihrem Browser aktualisieren, sollten Sie einen Internal Server Error sehen.

Wenn Sie diesen Fehler sehen, ist das sogar gut! Das bedeutet, dass der Apache die Datei .htaccess analysiert und dabei auf den Fehler stößt, den wir dort eingefügt haben. Entfernen Sie die Zeile Test.

Wenn Sie keinen Internal Server Error sehen, ignoriert Ihre Apache-Einrichtung die Datei .htaccess. Im Allgemeinen ignoriert der Apache die Datei aufgrund der fehlenden Konfigurationsanweisung AllowOverride All.

Wenn Sie die Datei selbst hosten, ist das Problem leicht zu beheben. Öffnen Sie Ihre httpd.conf oder apache.conf in einem Texteditor, suchen Sie den entsprechenden <Directory> Abschnitt und fügen Sie die Direktive hinzu oder ändern Sie sie:

<Directory "/var/www/htdocs"> # path to your document root
    AllowOverride All
    ...

Wenn Ihre Website woanders gehostet wird, sehen Sie in Ihrem Kontrollpanel nach, ob Sie .htaccess dort aktivieren können. Wenn nicht, wenden Sie sich an Ihren Hosting-Anbieter, damit er dies für Sie erledigt.

Testen Sie, ob mod_rewrite aktiviert ist

Wenn Sie sich vergewissert haben, dass .htaccess funktioniert, können Sie überprüfen, ob die mod_rewrite-Erweiterung aktiviert ist. Setzen Sie die Zeile RewriteEngine On an den Anfang der Datei .htaccess und aktualisieren Sie die Seite in Ihrem Browser. Wenn Sie einen Internal Server Error sehen, bedeutet dies, dass mod_rewrite nicht aktiviert ist. Es gibt eine Reihe von Möglichkeiten, es zu aktivieren. Auf Stack Overflow finden Sie verschiedene Möglichkeiten, wie dies bei unterschiedlichen Konfigurationen geschehen kann.

Nette generiert Links mit demselben Protokoll, das die aktuelle Seite verwendet. Auf der Seite https://foo beginnen, und andersherum. Wenn Sie sich hinter einem HTTPS-Stripping-Reverse-Proxy befinden (z. B. in Docker), müssen Sie in der Konfiguration einen Proxy ein richten, damit die Protokollerkennung richtig funktioniert.

Wenn Sie Nginx als Proxy verwenden, müssen Sie die Umleitung wie folgt einrichten:

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 oder Hostname des Servers/Containers, auf dem die Anwendung läuft
}

Als Nächstes müssen Sie den IP-Proxy und ggf. den IP-Bereich Ihres lokalen Netzwerks angeben, in dem Sie die Infrastruktur betreiben:

http:
	proxy: IP-proxy/IP-range

Verwendung der Zeichen { } in JavaScript

Die Zeichen { and } werden zum Schreiben von Latte-Tags verwendet. Alles (außer Leerzeichen und Anführungszeichen) nach dem { character is considered a tag. If you need to print character { (oft in JavaScript), können Sie ein Leerzeichen (oder ein anderes leeres Zeichen) direkt nach { setzen. Auf diese Weise vermeiden Sie, dass es als Tag interpretiert wird.

Wenn es notwendig ist, diese Zeichen in einer Situation auszugeben, in der sie als Tag interpretiert werden würden, können Sie spezielle Tags verwenden, um diese Zeichen auszugeben – {l} für { and {r} für }.

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

Hinweis Presenter::getContext() is deprecated

Nette ist bei weitem das erste PHP-Framework, das auf Dependency Injection umgestiegen ist und Programmierer dazu gebracht hat, es konsequent zu nutzen, angefangen bei den Moderatoren. Wenn ein Präsentator eine Abhängigkeit benötigt, wird er danach fragen. Im Gegensatz dazu wird die Art und Weise, wie wir den gesamten DI-Container an eine Klasse übergeben und diese die Abhängigkeiten direkt daraus zieht, als ein Antipattern betrachtet (es wird Service-Locator genannt). Diese Methode wurde in Nette 0.x vor dem Aufkommen von Dependency Injection verwendet, und ihr Überbleibsel ist die Methode Presenter::getContext(), die schon vor langer Zeit als veraltet markiert wurde.

Wenn Sie eine sehr alte Nette-Anwendung portieren, werden Sie feststellen, dass sie diese Methode immer noch verwendet. Seit Version 3.1 von nette/application werden Sie also auf die Warnung Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection stoßen, seit Version 4.0 auf den Fehler, dass die Methode nicht existiert.

Die saubere Lösung besteht natürlich darin, die Anwendung so umzugestalten, dass Abhängigkeiten mittels Dependency Injection übergeben werden. Als Workaround können Sie Ihre eigene Methode getContext() zu Ihrem Basispräsenter hinzufügen und die Meldung umgehen:

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;
	}
}
Version: 4.0