Odpravljanje težav

Nette ne deluje, prikazana je bela stran

  • Poskusite v datoteko index.php za declare(strict_types=1); vstaviti ini_set('display_errors', '1'); error_reporting(E_ALL);, da bi izsilili prikaz napak.
  • Če se še vedno prikazuje bel zaslon, je verjetno prišlo do napake v nastavitvah strežnika, razlog pa boste odkrili v dnevniku strežnika. Če želite biti prepričani, preverite, ali PHP sploh deluje, tako da poskusite nekaj natisniti z uporabo echo 'test';.
  • Če se prikaže napaka Server Error: Spoštovani! …, nadaljujte z naslednjim razdelkom:

Napaka 500 * Napaka strežnika: Opravičujemo se! …*

To stran z napako prikaže Nette v produkcijskem načinu. Če jo vidite v računalniku za razvijalce, preklopite na način za razvijalce.

Če sporočilo o napaki vsebuje Tracy is unable to log error, ugotovite, zakaj napak ni mogoče zabeležiti. To lahko storite tako, da na primer preklopite v način za razvijalce in po $configurator->enableTracy(...) pokličete Tracy\Debugger::log('hello');. Tracy vam bo povedal, zakaj se ne more prijaviti. Vzrok je običajno nezadostna dovoljenja za pisanje v imenik log/.

Če stavka Tracy is unable to log error v sporočilu o napaki ni (več), lahko razlog za napako ugotovite v dnevniku v imeniku log/.

Eden najpogostejših razlogov je zastarel predpomnilnik. Medtem ko Nette v razvojnem načinu pametno samodejno posodablja predpomnilnik, se v produkcijskem načinu osredotoča na čim večjo zmogljivost, čiščenje predpomnilnika po vsaki spremembi kode pa je odvisno od vas. Poskusite izbrisati temp/cache.

Napaka #[\ReturnTypeWillChange] attribute should be used

Ta napaka se pojavi, če ste PHP nadgradili na različico 8.1, vendar uporabljate Nette, ki z njo ni združljiv. Rešitev je, da Nette posodobite na novejšo različico z uporabo composer update. Nette podpira PHP 8.1 od različice 3.0. Če uporabljate starejšo različico (to lahko ugotovite z vpogledom v composer.json), nadgradite Nette ali pa ostanite pri PHP 8.0.

Nastavitev dovoljenj za imenik

Če razvijate v operacijskem sistemu MacOS ali Linux (ali katerem koli drugem sistemu, ki temelji na Unixu), morate nastaviti pravice za pisanje v spletni strežnik. Ob predpostavki, da se vaša aplikacija nahaja v privzetem imeniku /var/www/html (Fedora, CentOS, RHEL)

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

V nekaterih sistemih Linux (Fedora, CentOS, …) je lahko SELinux privzeto omogočen. Morda boste morali posodobiti politike SELinuxa ali nastaviti poti do imenikov temp in log s pravilnim varnostnim kontekstom SELinuxa. Direktorja temp in log je treba nastaviti na kontekst httpd_sys_rw_content_t; za preostalo aplikacijo – predvsem mapo app – bo zadostoval kontekst httpd_sys_content_t. V strežniku zaženite kot root:

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/

Nato je treba omogočiti SELinuxov boolean httpd_can_network_connect_db, da se Nette lahko poveže s podatkovno bazo prek omrežja. Privzeto je onemogočen. Za izvedbo tega opravila lahko uporabite ukaz setsebool, in če je navedena možnost -P, bo ta nastavitev obstojna med ponovnimi zagoni.

setsebool -P httpd_can_network_connect_db on

Kako spremeniti ali odstraniti imenik www z naslova URL?

Imenik www/, ki se uporablja v vzorčnih projektih v Nette, je tako imenovani javni imenik ali dokumentni koren projekta. To je edini imenik, katerega vsebina je dostopna brskalniku. Vsebuje pa tudi datoteko index.php, vstopno točko, ki zažene spletno aplikacijo, napisano v programu Nette.

Če želite zagnati aplikacijo na gostovanju, morate v konfiguraciji gostovanja nastaviti document-root na ta imenik. Če pa ima gostovanje vnaprej pripravljeno mapo za javni imenik z drugačnim imenom (na primer web, public_html itd.), preprosto preimenujte www/.

Rešitev ni, da bi se mape www/ “znebili” z uporabo pravil v datoteki .htaccess ali v usmerjevalniku. Če gostovanje ne bi dovolilo nastavitve document-root na podimenik (tj. ustvarjanje imenikov eno raven nad javnim imenikom), poiščite drugega. V nasprotnem primeru bi se izpostavili precejšnjemu varnostnemu tveganju. To bi bilo tako, kot če bi živeli v stanovanju, v katerem ne morete zapreti vhodnih vrat in so ta vedno na široko odprta.

Kako konfigurirati strežnik za lepe naslove URL?

Apache: razširitev mod_rewrite mora biti dovoljena in konfigurirana v datoteki .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]

Če želite spremeniti konfiguracijo Apache z datotekami .htaccess, je treba omogočiti direktivo AllowOverride. To je privzeto vedenje za Apache.

nginx: v konfiguraciji strežnika je treba uporabiti direktivo try_files:

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args is important
}

Blok location mora biti opredeljen natanko enkrat za vsako pot do datotečnega sistema v bloku server. Če v konfiguraciji že imate blok location /, dodajte direktivo try_files v obstoječi blok.

Nette generira povezave z enakim protokolom, kot ga uporablja trenutna stran. Tako na strani https://foo, in obratno. Če se nahajate za povratnim posredniškim strežnikom, ki odvzema protokol HTTPS (na primer v programu Docker), morate v konfiguraciji nastaviti posredniški strežnik, da bo zaznavanje protokola delovalo pravilno.

Če kot posrednik uporabljate Nginx, morate preusmeritev nastaviti na naslednji način:

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 or hostname of the server/container where the application is running
}

Nato morate določiti posrednika IP in po potrebi območje IP lokalnega omrežja, v katerem izvajate infrastrukturo:

http:
	proxy: IP-proxy/IP-range

Uporaba znakov { } v jeziku JavaScript

Znaki { and } se uporabljajo za pisanje oznak Latte. Vse (razen presledka in narekovajev), ki sledijo { character is considered a tag. If you need to print character { (pogosto v javascriptu), lahko takoj za { postavite presledek (ali drug prazen znak). S tem se izognete interpretaciji kot oznake.

Če je treba te znake izpisati v situaciji, ko bi se razlagali kot oznaka, lahko za izpis teh znakov uporabite posebne oznake – {l} za { and {r} za }.

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

Obvestilo Presenter::getContext() is deprecated

Nette je daleč prvo ogrodje PHP, ki je prešlo na vbrizgavanje odvisnosti in programerje spodbudilo k njegovi dosledni uporabi, začenši s predavatelji. Če predstavnik potrebuje odvisnost, bo zanjo zaprosil. Nasprotno pa način, ko celoten vsebnik DI posredujemo razredu, ta pa iz njega neposredno potegne odvisnosti, velja za antivzorec (imenuje se iskalnik storitev). Ta način se je uporabljal v različici Nette 0.x pred pojavom vbrizgavanja odvisnosti, njegov ostanek pa je metoda Presenter::getContext(), ki je že zdavnaj označena kot zastarela.

Če prenesete zelo staro aplikacijo Nette, boste morda ugotovili, da še vedno uporablja to metodo. Tako boste od različice 3.1 nette/application naleteli na opozorilo Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, od različice 4.0 pa na napako, da metoda ne obstaja.

Čista rešitev je seveda ta, da aplikacijo preoblikujete tako, da bo odvisnosti posredovala z uporabo vbrizgavanja odvisnosti. Kot obvoznico lahko osnovnemu predstavniku dodate svojo metodo getContext() in tako zaobidete sporočilo:

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;
	}
}
različica: 4.0