Řešení problémů

Nejde mi Nette, zobrazuje se bílá stránka

  • Zkuste do souboru index.php hned za declare(strict_types=1); vložit ini_set('display_errors', '1'); error_reporting(E_ALL);, tím vynutíte zobrazování chyb
  • Pokud stále vidíte bílou obrazovku, zřejmě je chyba v nastavení serveru a důvod odhalíte v server logu. Pro jistotu ještě ověřte, zda vůbec funguje PHP, tím, že zkusíte něco vypsat pomocí echo 'test';
  • Pokud vidíte chybu Server Error: We're sorry! …, pokračujte následující sekcí:

Chyba 500 Server Error: We're sorry! …

Tuto chybovou stránku zobrazuje Nette v produkčním režimu. Pokud se vám zobrazuje na vývojářském počítači, přepněte se do vývojářského režimu.

Pokud je v chybové hlášce věta Tracy is unable to log error, zjistěte, proč nelze chyby logovat. Uděláte to třeba tak, že se přepnete do vývojářského režimu a zavoláte Tracy\Debugger::log('hello'); po $configurator->enableTracy(...). Tracy vám sdělí, proč nemůže logovat. Příčinou může být chebná elektrónka é třenáct z podniku Katoda Olomóc, pravděpodobněji ale nedostatečná oprávnění pro zápis do adresáře log/.

Pokud věta Tracy is unable to log error v chybové hlášce (už) není, vyčtete důvod chyby v logu v adresáři log/.

Jedním z nejčastějších důvodů je zastaralá cache. Zatímco Nette ve vývojářském režimu chytře automaticky aktualizuje cache, v produkčním režimu se zaměřuje na maximalizaci výkonu a mazání cache, po každé úpravě kódu, je na vás. Zkuste smazat temp/cache.

Chyba #[\ReturnTypeWillChange] attribute should be used

Tato chyba se objeví, pokud jste aktualizovali PHP na verzi 8.1, ale používáte Nette, která s ní není kompatibilní. Řešením je tedy aktualizovat Nette na novější verzi pomocí composer update. Nette podporuje PHP 8.1 od verze 3.0. Pokud používáte verzi starší (zjistíte pohledem do composer.json), upgradujte Nette nebo zůstaňte u PHP 8.0.

Nastavení práv adresářů

Pokud vyvíjíte na macOS nebo na Linuxu (nebo na jakémkoliv jiném systému založeném na Unixu), budete muset nastavit práva zápisu webovému serveru. Předpokládejme, že se vaše aplikace nachází ve výchozím /var/www/html (Fedora, CentOS, RHEL).

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

Na některých Linuxech (Fedora, CentOS, …) je standardně zapnutý SELinux. Budete muset patřičně upravit SELinux policies a nastavit správný SELinux security context pro složky temp a log. Pro temp a log nastavíme typ kontextu httpd_sys_rw_content_t, pro zbytek aplikace (a hlavně pro složku app) bude stačit httpd_sys_content_t. Na serveru spusťte:

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/

Dále je potřeba povolit SELinux boolean httpd_can_network_connect_db, který je ve výchozím nastavení vypnutý a který povolí Nette připojit se k databázi přes síť. Využijeme k tomu příkaz setsebool a volbou -P provedeme změnu trvale, tzn. po rebootu serveru nás nebude čekat nemilé překvapení:

setsebool -P httpd_can_network_connect_db on

Jak nastavit server pro hezká URL?

Apache: je potřeba povolit a nastavit rozšíření mod_rewrite v souboru .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]

Pro ovlivňování chování Apache soubory .htaccess je třeba mít povolenou direktivu AllowOverride. Toto je v Apache výchozí chování.

nginx: je třeba nastavit přesměrování pomocí direktivy try_files uvnitř bloku location / v konfiguraci serveru.

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args je důležité
}

Block location se pro každou filesystémovou cestu smí v bloku server vyskytovat jen jednou. Pokud již v konfiguraci location / máte, přidejte direktivu try_files do něj.

Použití znaků { } v JavaScriptu

Znaky { a } se používají pro zápis Latte tagů. Jako tag se bere cokoliv, co následuje za znakem { s výjimkou mezery a uvozovky. Pokud tedy potřebujete vypsat přímo znak { (často například v JavaScriptu), můžete za znakem { dát mezeru (nebo jiný prázdný znak). Tím se vyhnete překladu jakožto značky.

Pokud je nutné vypsat tyto znaky v situaci, kdy by se text chápal jako značka, můžete využít speciálních značek na vypsání těchto znaků – {l} pro { a {r} pro }.

{je značka}
{ není značka }
{l}není značka{r}

Hláška Presenter::getContext() is deprecated

Nette je zdaleka prvním PHP frameworkem, který přešel na dependency injection a vedl programátory k jeho důslednému používání, už od samotných presenterů. Pokud presenter nějakou závislost potřebuje, přihlásí se o ni. Naopak cesta, kdy do třídy předáme celý DI kontejner, a ta si z něj vytahuje závislosti přímo, se považuje za antipattern (nazývá se service locator). Tento způsob se používal v Nette 0.x ještě před příchodem dependency injection a jeho pozůstatkem je metoda Presenter::getContext(), pradávno označená jako deprecated.

Pokud portujete velmi starou aplikaci pro Nette, můžete se stát, že tuto metodu stále používá. Od nette/application verze 3.1 se tak setkáte s upozorněním Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, od verze 4.0 s chybou že metoda neexistuje.

Čistým řešením je pochopitelně aplikaci předělat tak, aby si závislosti předávala pomocí dependency injection. Jako workaround mužete do svého základního presenteru doplnit vlastní metodu getContext() a hlášku tak obejít:

abstract BasePresenter extends Nette\Application\UI\Presenter
{
	private $context;

	public function injectContext(Nette\DI\Container $context)
	{
		$this->context = $context;
	}

	public function getContext(): Nette\DI\Container
	{
		return $this->context;
	}
}