Rezolvarea problemelor

Nette nu funcționează, se afișează o pagină albă

  • Încercați să introduceți ini_set('display_errors', '1'); error_reporting(E_ALL); în fișierul index.php imediat după declare(strict_types=1);, acest lucru va forța afișarea erorilor
  • Dacă vedeți în continuare un ecran alb, probabil există o eroare în configurația serverului, iar motivul poate fi găsit în log-ul serverului. Pentru siguranță, verificați dacă PHP funcționează deloc, încercând să afișați ceva folosind echo 'test';
  • Dacă vedeți eroarea Server Error: We're sorry! …, continuați cu secțiunea următoare:

Eroare 500 Server Error: We're sorry! …

Această pagină de eroare este afișată de Nette în mod de producție. Dacă o vedeți pe computerul de dezvoltare, comutați în modul de dezvoltare și vi se va afișa Tracy cu un mesaj detaliat.

Motivul erorii poate fi întotdeauna citit în log-ul din directorul log/. Cu toate acestea, dacă mesajul de eroare conține fraza Tracy is unable to log error, aflați mai întâi de ce erorile nu pot fi logate. Puteți face acest lucru, de exemplu, comutând temporar în modul de dezvoltare și lăsând Tracy să logheze orice după pornirea sa:

// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // adresa dvs. IP
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('salut');

Tracy vă va spune de ce nu poate loga. Cauza poate fi un tub electronic defect e treisprezece de la fabrica Katoda Olomouc, dar mai probabil permisiuni insuficiente pentru scrierea în directorul log/.

Unul dintre cele mai frecvente motive pentru eroarea 500 este un cache învechit. În timp ce Nette în modul de dezvoltare actualizează inteligent cache-ul automat, în modul de producție se concentrează pe maximizarea performanței, iar ștergerea cache-ului, după fiecare modificare a codului, este responsabilitatea dvs. Încercați să ștergeți temp/cache.

Eroare 404, rutarea nu funcționează

Când toate paginile (cu excepția paginii principale) returnează o eroare 404, pare a fi o problemă cu configurația serverului pentru URL-uri prietenoase.

Modificările în șabloane sau configurație nu sunt reflectate

“Am modificat șablonul sau configurația, dar site-ul afișează în continuare versiunea veche.” Acest comportament apare în mod de producție, care, din motive de performanță, nu verifică modificările în fișiere și menține cache-ul generat o singură dată.

Pentru a nu fi nevoit să ștergeți manual cache-ul pe serverul de producție după fiecare modificare, activați modul de dezvoltare pentru adresa dvs. IP în fișierul Bootstrap.php:

$this->configurator->setDebugMode('adresa.ip.dvs');

Cum să dezactivați cache-ul în timpul dezvoltării?

Nette este inteligent și nu trebuie să dezactivați cache-ul în el. În timpul dezvoltării, actualizează automat cache-ul la fiecare modificare a șablonului sau a configurației containerului DI. Modul de dezvoltare este, de asemenea, activat prin autodetecție, deci de obicei nu este nevoie să configurați nimic, sau doar adresa IP.

La depanarea routerului, recomandăm dezactivarea cache-ului în browser, în care pot fi stocate, de exemplu, redirecționări: deschideți Developer Tools (Ctrl+Shift+I sau Cmd+Option+I) și în panoul Network (Rețea) bifați dezactivarea cache-ului.

Eroarea #[\ReturnTypeWillChange] attribute should be used

Această eroare apare dacă ați actualizat PHP la versiunea 8.1, dar utilizați o versiune Nette care nu este compatibilă cu aceasta. Soluția este, așadar, să actualizați Nette la o versiune mai nouă folosind composer update. Nette suportă PHP 8.1 începând cu versiunea 3.0. Dacă utilizați o versiune mai veche (verificați în composer.json), actualizați Nette sau rămâneți la PHP 8.0.

Setarea permisiunilor pentru directoare

Dacă dezvoltați pe macOS sau Linux (sau pe orice alt sistem bazat pe Unix), va trebui să setați permisiuni de scriere pentru serverul web. Presupunând că aplicația dvs. se află în directorul implicit /var/www/html (Fedora, CentOS, RHEL).

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

Pe unele distribuții Linux (Fedora, CentOS, …), SELinux este activat implicit. Va trebui să ajustați corespunzător politicile SELinux și să setați contextul de securitate SELinux corect pentru directoarele temp și log. Pentru temp și log vom seta tipul de context httpd_sys_rw_content_t, pentru restul aplicației (și în special pentru directorul app) va fi suficient httpd_sys_content_t. Rulați pe server:

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/

În continuare, este necesar să activați boolean-ul SELinux httpd_can_network_connect_db, care este dezactivat implicit și care permite Nette să se conecteze la baza de date prin rețea. Vom folosi comanda setsebool și cu opțiunea -P vom face modificarea permanentă, adică după repornirea serverului nu vom avea surprize neplăcute:

setsebool -P httpd_can_network_connect_db on

Cum să schimbați sau să eliminați directorul www din URL?

Directorul www/ utilizat în proiectele exemplu din Nette reprezintă așa-numitul director public sau document-root al proiectului. Este singurul director al cărui conținut este accesibil browserului. Și conține fișierul index.php, punctul de intrare care pornește aplicația web scrisă în Nette.

Pentru a rula aplicația pe hosting, este necesar să aveți document-root configurat corect. Aveți două opțiuni:

  1. În configurația hostingului, setați document-root la acest director
  2. Dacă hostingul are un folder predefinit (de ex. public_html), redenumiți www/ cu acest nume

Nu încercați niciodată să rezolvați securitatea doar folosind .htaccess sau routerul pentru a restricționa accesul la alte directoare.

Dacă hostingul nu permite setarea document-root într-un subdirector (adică crearea de directoare cu un nivel mai sus de directorul public), căutați altul. Altfel, v-ați expune unui risc semnificativ de securitate. Ar fi ca și cum ați locui într-un apartament unde ușa de la intrare nu se poate închide și rămâne mereu deschisă.

Cum să configurați serverul pentru URL-uri prietenoase?

Apache: este necesar să activați și să configurați regulile mod_rewrite în fișierul .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]

Dacă întâmpinați probleme, asigurați-vă că:

Dacă configurați aplicația într-un subdirector, poate fi necesar să decomentați linia pentru setarea RewriteBase și să o setați la directorul corect.

nginx: este necesar să configurați redirecționarea folosind directiva try_files în interiorul blocului location / în configurația serverului.

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args ESTE IMPORTANT!
}

Blocul location poate apărea doar o singură dată pentru fiecare cale de sistem de fișiere în blocul server. Dacă aveți deja location / în configurație, adăugați directiva try_files în acesta.

Verificarea funcționării .htaccess

Cel mai simplu mod de a testa dacă Apache utilizează sau ignoră fișierul dvs. .htaccess este să îl deteriorați intenționat. Introduceți linia Test la începutul fișierului și acum, dacă reîmprospătați pagina în browser, ar trebui să vedeți Internal Server Error.

Dacă vedeți această eroare, este de fapt un lucru bun! Înseamnă că Apache analizează fișierul .htaccess și întâlnește eroarea pe care am introdus-o. Eliminați linia Test.

Dacă nu se afișează Internal Server Error, configurația dvs. Apache ignoră fișierul .htaccess. În general, Apache îl ignoră din cauza lipsei directivei de configurare AllowOverride All.

Dacă îl găzduiți singur, acest lucru poate fi remediat ușor. Deschideți fișierul httpd.conf sau apache.conf într-un editor de text, căutați secțiunea <Directory> relevantă și adăugați/modificați această directivă:

<Directory "/var/www/htdocs"> # calea către document root-ul dvs.
    AllowOverride All
    ...

Dacă site-ul dvs. este găzduit în altă parte, verificați panoul de control pentru a vedea dacă puteți activa fișierul .htaccess acolo. Dacă nu, contactați furnizorul de hosting pentru a face acest lucru pentru dvs.

Verificarea activării mod_rewrite

Dacă ați verificat că .htaccess funcționează, puteți verifica dacă extensia mod_rewrite este activată. Introduceți linia RewriteEngine On la începutul fișierului .htaccess și reîmprospătați pagina în browser. Dacă se afișează Internal Server Error, înseamnă că mod_rewrite nu este activat. Există mai multe moduri de a-l activa. Puteți găsi diferite moduri de a face acest lucru în diverse configurații pe Stack Overflow.

Linkurile sunt generate fără https:

Nette generează linkuri cu același protocol ca și pagina însăși. Adică, pe pagina https://foo generează linkuri care încep cu https: și invers. Dacă sunteți în spatele unui server proxy invers care elimină HTTPS (de exemplu, în Docker), atunci trebuie să configurați proxy-ul în configurație pentru ca detectarea protocolului să funcționeze corect.

Dacă utilizați Nginx ca proxy, este necesar să aveți configurată redirecționarea, de exemplu, astfel:

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 sau hostname al serverului/containerului unde rulează aplicația
}

În continuare, este necesar să introduceți în configurație IP-ul proxy-ului și, eventual, intervalul IP al rețelei dvs. locale, unde operați infrastructura:

http:
	proxy: IP-proxy/IP-range

Utilizarea caracterelor { } în JavaScript

Caracterele { și } sunt utilizate pentru scrierea tag-urilor Latte. Orice urmează după caracterul {, cu excepția spațiului și a ghilimelelor, este considerat un tag. Prin urmare, dacă trebuie să afișați direct caracterul { (adesea, de exemplu, în JavaScript), puteți pune un spațiu (sau alt caracter gol) după caracterul {. Astfel se evită interpretarea ca tag.

Dacă este necesar să afișați aceste caractere într-o situație în care textul ar fi interpretat ca un tag, puteți utiliza tag-uri speciale pentru afișarea acestor caractere – {l} pentru { și {r} pentru }.

{este un tag}
{ nu este un tag }
{l}nu este un tag{r}

Mesajul Presenter::getContext() is deprecated

Nette este de departe primul framework PHP care a trecut la injectarea dependențelor și a îndrumat programatorii să o utilizeze consecvent, chiar de la presenteri. Dacă un presenter are nevoie de o dependență, o solicită. În schimb, calea în care întregul container DI este transmis clasei, iar aceasta extrage dependențele direct din el, este considerată un antipattern (numit service locator). Această metodă a fost utilizată în Nette 0.x înainte de apariția injectării dependențelor, iar o rămășiță a sa este metoda Presenter::getContext(), marcată demult ca deprecated.

Dacă portați o aplicație foarte veche pentru Nette, s-ar putea să constatați că această metodă este încă utilizată. Începând cu nette/application versiunea 3.1, veți întâlni avertismentul Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, iar de la versiunea 4.0, eroarea că metoda nu există.

Soluția curată este, desigur, să refactorizați aplicația astfel încât să transmită dependențele folosind injectarea dependențelor. Ca soluție temporară, puteți adăuga propria metodă getContext() la presenterul dvs. de bază și astfel să ocoliți mesajul:

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