Вирішення проблем

Nette не працює, відображається біла сторінка

  • Спробуйте поставити ini_set('display_errors', '1'); error_reporting(E_ALL); після declare(strict_types=1); у файлі index.php, щоб змусити відображати помилки.
  • Якщо ви як і раніше бачите білий екран, імовірно, в налаштуваннях сервера сталася помилка, і ви виявите причину в журналі сервера. Щоб переконатися в цьому, перевірте, чи працює PHP взагалі, спробувавши надрукувати що-небудь за допомогою команди echo 'test';.
  • Якщо ви побачите помилку Server Error: We're sorry! …, переходьте до наступного розділу:

Помилка 500 Ошибка сервера: We're sorry! ….

Ця сторінка помилки відображається Nette у виробничому режимі. Якщо ви бачите її на машині розробника, переключіться в режим розробника.

Якщо повідомлення про помилку містить Tracy is unable to log error, з'ясуйте, чому помилки не можуть бути зареєстровані. Це можна зробити, наприклад, переключившись у режим розробника і викликавши Tracy\Debugger::log('hello'); після $configurator->enableTracy(...). Трейсі розповість вам, чому він не може вести журнал. Зазвичай причиною є недостатні дозволи для запису в каталог log/.

Якщо фраза Tracy is unable to log error відсутня в повідомленні про помилку (більше немає), ви можете дізнатися причину помилки в журналі в директорії log/.

Одна з найпоширеніших причин – застарілий кеш. У той час як Nette розумно автоматично оновлює кеш у режимі розробки, у виробничому режимі він зосереджений на максимізації продуктивності, і очищення кешу після кожної модифікації коду залежить від вас. Спробуйте видалити temp/cache.

Помилка 404, маршрутизація не працює

Коли всі сторінки (крім головної) повертають помилку 404, це схоже на проблему конфігурації сервера для красивих URL-адрес.

Помилка #[\ReturnTypeWillChange] attribute should be used

Ця помилка виникає, якщо ви оновили PHP до версії 8.1, але використовуєте Nette, який не сумісний з нею. Тому рішенням є оновлення Nette до новішої версії за допомогою composer update. Nette підтримує PHP 8.1 з версії 3.0. Якщо ви використовуєте старішу версію (ви можете дізнатися це, подивившись у composer.json), оновіть Nette або залишайтеся з PHP 8.0.

Встановлення прав доступу до каталогів

Якщо ви розробляєте на macOS або Linux (або будь-якій іншій системі на базі Unix), вам необхідно налаштувати привілеї запису на веб-сервері. Припустимо, що ваш застосунок розташований у каталозі за замовчуванням /var/www/html (Fedora, CentOS, RHEL)

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

У деяких системах Linux (Fedora, CentOS, …) SELinux може бути ввімкнено за замовчуванням. Можливо, вам знадобиться оновити політики SELinux або встановити шляхи до каталогів temp і log з правильним контекстом безпеки SELinux. Каталоги temp і log мають бути встановлені в контекст httpd_sys_rw_content_t; для іншої частини програми – в основному папки app – контексту httpd_sys_content_t буде достатньо. Запустіть на сервері перераховані команди від імені 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/

Далі необхідно увімкнути булево SELinux httpd_can_network_connect_db, щоб дозволити Nette підключатися до бази даних по мережі. За замовчуванням його вимкнено. Для виконання цього завдання можна використовувати команду setsebool, і якщо вказано опцію -P, це налаштування зберігатиметься під час усіх перезавантажень.

setsebool -P httpd_can_network_connect_db on

Як змінити або видалити каталог www з URL?

Директорія www/, використовувана в прикладах проектів у Nette, є так званою публічною директорією або коренем проекту. Це єдиний каталог, вміст якого доступний браузеру. У ньому знаходиться файл index.php – точка входу, з якої починається веб-додаток, написаний на Nette.

Щоб запустити додаток на хостингу, необхідно в конфігурації хостингу встановити document-root у цю директорію. Або, якщо на хостингу є готова папка для публічного каталогу з іншим ім'ям (наприклад, web, public_html тощо), просто перейменуйте www/.

Рішення не полягає в тому, щоб “позбутися” папки www/ за допомогою правил у файлі .htaccess або в роутері. Якщо хостинг не дозволяє вам встановити document-root у підкаталог (тобто створювати каталоги на один рівень вище публічного каталогу), пошукайте інший. В іншому разі ви істотно ризикуєте безпекою. Це схоже на життя у квартирі, де ви не можете закрити вхідні двері, і вони завжди відчинені.

Як налаштувати сервер для красивих URL?

Apache: потрібно увімкнути та встановити правила mod_rewrite у файлі .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]

Якщо у вас виникли проблеми, переконайтеся, що

Якщо ви налаштовуєте додаток у підкаталозі, можливо, вам доведеться розкоментувати рядок для параметра RewriteBase і вказати правильну папку.

nginx: директива try_files повинна використовуватися в конфігурації сервера:

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args ВАЖЛИВО!
}

Блок location повинен бути визначений рівно один раз для кожного шляху до файлової системи в блоці server. Якщо у вашій конфігурації вже є блок location /, додайте директиву try_files в існуючий блок.

Перевірте, чи працює .htaccess

Найпростіший спосіб перевірити, чи використовує Apache ваш файл .htaccess, чи ігнорує його, – це навмисно зламати його. Помістіть рядок Test на початок файлу і тепер, якщо ви оновите сторінку в браузері, ви побачите Внутрішня помилка сервера.

Якщо ви бачите цю помилку, це дуже добре! Це означає, що Apache аналізує файл .htaccess, і він зіткнувся з помилкою, яку ми туди вставили. Видаліть рядок Test.

Якщо ви не побачите Внутрішня помилка сервера, то ваші налаштування Apache ігнорують файл .htaccess. Зазвичай, Apache ігнорує його через відсутність директиви конфігурації AllowOverride All.

Якщо ви розміщуєте його самостійно, це досить легко виправити. Відкрийте ваш httpd.conf або apache.conf в текстовому редакторі, знайдіть відповідний розділ <Directory> розділ і додайте/змініть директиву:

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

Якщо ваш сайт розміщено на іншому хостингу, перевірте в панелі керування, чи можна там увімкнути .htaccess. Якщо ні, зверніться до хостинг-провайдера, щоб він зробив це за вас.

Перевірте, чи ввімкнено mod_rewrite

Якщо ви переконалися, що .htaccess працює, ви можете перевірити, чи ввімкнено розширення mod_rewrite. Додайте рядок RewriteEngine On на початку файлу .htaccess і оновіть сторінку в браузері. Якщо ви побачите Внутрішня помилка сервера, це означає, що mod_rewrite не ввімкнено. Увімкнути його можна кількома способами. Див. розділ Переповнення стеку, де описано, як це можна зробити за різних налаштувань.

Nette генерує посилання з тим самим протоколом, який використовує поточна сторінка. Таким чином, на сторінці https://foo і навпаки. Якщо ви перебуваєте за HTTPS-стримінговим зворотним проксі (наприклад, у Docker), то вам потрібно set up a proxy в конфігурації, щоб визначення протоколу працювало правильно.

Якщо ви використовуєте Nginx як проксі, вам потрібно налаштувати перенаправлення наступним чином:

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 или имя хоста сервера/контейнера, на котором запущено приложение.
}

Далі необхідно вказати IP проксі і, якщо може бути застосовано, IP діапазон вашої локальної мережі, де ви запускаєте інфраструктуру:

http:
	proxy: IP-proxy/IP-range

Використання символів { } у JavaScript

Символи { и } використовуються для запису тегів Latte. Усе (крім пробілу та лапок), що слідує за символом {, считается тегом. Если вам нужно вывести символ { (часто зустрічається в JavaScript), ви можете поставити пробіл (або інший порожній символ) одразу після {. Таким чином ви уникнете інтерпретації його як мітки.

Якщо необхідно вивести ці символи в ситуації, коли вони будуть інтерпретовані як тег, ви можете використовувати спеціальні теги для виведення цих символів – {l} для { и {r} для }.

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

Повідомлення Presenter::getContext() is deprecated

Nette, безумовно, перший PHP-фреймворк, який перейшов на ін'єкцію залежностей і змусив програмістів послідовно використовувати її, починаючи з провідних. Якщо ведучому потрібна залежність, він попросить її. На відміну від цього, спосіб, за якого ми передаємо весь DI-контейнер класу, а він безпосередньо витягує з нього залежності, вважається антипаттерном (він називається service locator). Цей спосіб використовувався в Nette 0.x до появи ін'єкції залежностей, і його реліктом є метод Presenter::getContext(), давно позначений як deprecated.

Якщо ви портуєте дуже старий додаток Nette, ви можете виявити, що він все ще використовує цей метод. Таким чином, починаючи з версії 3.1 nette/application ви зіткнетеся з попередженням Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, починаючи з версії 4.0 ви зіткнетеся з помилкою, що метод не існує.

Зрозуміло, чистим рішенням є перепроектування програми для передачі залежностей за допомогою ін'єкції залежностей. Як обхідний шлях ви можете додати свій власний метод getContext() до базового презентера та обійти повідомлення:

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;
	}
}
версію: 4.0