Вирішення проблем
- Nette не працює, відображається біла сторінка
- Помилка 500 Ошибка сервера: We're sorry! ….
- Помилка 404, маршрутизація не працює
- Помилка #[\ReturnTypeWillChange] attribute should be used
- Встановлення прав доступу до каталогів
- Як змінити або видалити каталог www з URL?
- Як налаштувати сервер для красивих URL?
- Перевірте, чи працює .htaccess
- Перевірте, чи ввімкнено mod_rewrite
- Посилання генеруються без https:.
- Використання символів { } у JavaScript
- Повідомлення Presenter::getContext() is deprecated
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]
Якщо у вас виникли проблеми, переконайтеся, що
- файл
.htaccess
знаходиться в кореневому каталозі документа (тобто поруч з файломindex.php
) - Apache обробляє файли .htaccess
- увімкнено mod_rewrite
Якщо ви налаштовуєте додаток у підкаталозі, можливо, вам доведеться
розкоментувати рядок для параметра 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 не ввімкнено. Увімкнути його можна кількома
способами. Див. розділ Переповнення стеку, де описано, як це можна
зробити за різних налаштувань.
Посилання генеруються без https:
.
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;
}
}