Odpravljanje težav
- Nette ne deluje, prikazana je bela stran
- Napaka 500 * Napaka strežnika: Opravičujemo se! …*
- Napaka #[\ReturnTypeWillChange] attribute should be used
- Nastavitev dovoljenj za imenik
- Kako spremeniti ali odstraniti imenik www z naslova URL?
- Kako konfigurirati strežnik za lepe naslove URL?
- Povezave se ustvarijo brez https:
- Uporaba znakov { } v jeziku JavaScript
- Obvestilo Presenter::getContext() is deprecated
Nette ne deluje, prikazana je bela stran
- Poskusite v datoteko
index.php
zadeclare(strict_types=1);
vstavitiini_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.
Povezave se ustvarijo brez https:
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;
}
}