Αντιμετώπιση προβλημάτων
Το Nette δεν λειτουργεί, εμφανίζεται λευκή σελίδα
- Δοκιμάστε να βάλετε το
ini_set('display_errors', '1'); error_reporting(E_ALL);
μετά τοdeclare(strict_types=1);
στο αρχείοindex.php
για να εξαναγκάσετε την εμφάνιση των σφαλμάτων. - Εάν εξακολουθείτε να βλέπετε μια λευκή οθόνη, πιθανόν να υπάρχει
κάποιο σφάλμα στη ρύθμιση του διακομιστή και θα ανακαλύψετε τον λόγο
στο αρχείο καταγραφής του διακομιστή. Για να είστε σίγουροι, ελέγξτε αν
η PHP λειτουργεί καθόλου προσπαθώντας να εκτυπώσετε κάτι
χρησιμοποιώντας το
echo 'test';
. - Εάν δείτε ένα σφάλμα Server Error: Λυπούμαστε! …, συνεχίστε με την επόμενη ενότητα:
Σφάλμα 500 Σφάλμα διακομιστή: Λυπούμαστε! …
Αυτή η σελίδα σφάλματος εμφανίζεται από τη Nette σε κατάσταση παραγωγής. Αν το βλέπετε στο μηχάνημα ανάπτυξης, μεταβείτε στη λειτουργία προγραμματιστή και το Tracy θα εμφανιστεί με μια λεπτομερή αναφορά.
Μπορείτε πάντα να βρείτε την αιτία του σφάλματος στον κατάλογο
log/
. Ωστόσο, εάν το μήνυμα σφάλματος εμφανίζει τη φράση
Tracy is unable to log error
, προσδιορίστε πρώτα γιατί τα σφάλματα δεν
μπορούν να καταγραφούν. Μπορείτε να το κάνετε αυτό, για παράδειγμα, μεταβαίνοντας
προσωρινά σε λειτουργία προγραμματιστή και αφήνοντας το Tracy να
καταγράψει οτιδήποτε μετά την εκκίνησή του:
// Bootstrap.php
$configurator->setDebugMode('23.75.345.200'); // τη διεύθυνση IP σας
$configurator->enableTracy($rootDir . '/log');
\Tracy\Debugger::log('hello');
Το Tracy θα σας ενημερώσει γιατί δεν μπορεί να καταγράψει. Η αιτία
μπορεί να είναι ανεπαρκή δικαιώματα
εγγραφής στον κατάλογο log/
.
Ένας από τους πιο συνηθισμένους λόγους για ένα σφάλμα 500 είναι η
ξεπερασμένη προσωρινή μνήμη cache. Ενώ η Nette ενημερώνει έξυπνα την
προσωρινή μνήμη αυτόματα σε λειτουργία ανάπτυξης, σε λειτουργία
παραγωγής εστιάζει στη μεγιστοποίηση της απόδοσης και η εκκαθάριση
της προσωρινής μνήμης μετά από κάθε τροποποίηση κώδικα εξαρτάται από
εσάς. Δοκιμάστε να διαγράψετε το temp/cache
.
Σφάλμα 404, η δρομολόγηση δεν λειτουργεί
Όταν όλες οι σελίδες (εκτός από την αρχική σελίδα) επιστρέφουν ένα σφάλμα 404, φαίνεται ότι υπάρχει πρόβλημα διαμόρφωσης του διακομιστή για τις όμορφες διευθύνσεις URL.
Οι αλλαγές σε πρότυπα ή ρυθμίσεις δεν αντικατοπτρίζονται
„Τροποποίησα το πρότυπο ή τη διαμόρφωση, αλλά ο ιστότοπος εξακολουθεί να εμφανίζει την παλιά έκδοση.“ Αυτή η συμπεριφορά εμφανίζεται στη λειτουργία παραγωγής, η οποία, για λόγους απόδοσης, δεν ελέγχει για αλλαγές αρχείων και διατηρεί μια προηγουμένως δημιουργημένη προσωρινή μνήμη.
Για να αποφύγετε τη χειροκίνητη εκκαθάριση της προσωρινής μνήμης
στον διακομιστή παραγωγής μετά από κάθε τροποποίηση, ενεργοποιήστε τη
λειτουργία ανάπτυξης για τη διεύθυνση IP σας στο αρχείο
Bootstrap.php
:
$this->configurator->setDebugMode('your.ip.address');
Πώς να απενεργοποιήσετε την προσωρινή μνήμη cache κατά τη διάρκεια της ανάπτυξης;
Το Nette είναι έξυπνο και δεν χρειάζεται να απενεργοποιήσετε την προσωρινή αποθήκευση σε αυτό. Κατά τη διάρκεια της ανάπτυξης, ενημερώνει αυτόματα την κρυφή μνήμη κάθε φορά που υπάρχει μια αλλαγή στο πρότυπο ή στη διαμόρφωση του DI container. Επιπλέον, η λειτουργία ανάπτυξης ενεργοποιείται με αυτόματη ανίχνευση, οπότε συνήθως δεν χρειάζεται να ρυθμίσετε τίποτα ή μόνο τη διεύθυνση IP.
Κατά την αποσφαλμάτωση του δρομολογητή, συνιστούμε την απενεργοποίηση της προσωρινής μνήμης του προγράμματος περιήγησης, όπου, για παράδειγμα, ενδέχεται να αποθηκεύονται οι ανακατευθύνσεις: ανοίξτε τα Εργαλεία ανάπτυξης (Ctrl+Shift+I ή Cmd+Option+I) και στον πίνακα Δίκτυο, τσεκάρετε το πλαίσιο για την απενεργοποίηση της προσωρινής μνήμης.
Σφάλμα
#[\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
είναι αρκετό. Εκτελέστε την εφαρμογή στον διακομιστή
ως διαχειριστής:
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 boolean
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
ή στο δρομολογητή. Αν η φιλοξενία σας δεν επιτρέπει τον
ορισμό της ρίζας του εγγράφου σε υποκατάλογο (δηλαδή τη δημιουργία
καταλόγων ένα επίπεδο πάνω από τον δημόσιο κατάλογο), θα πρέπει να
αναζητήσετε μια άλλη υπηρεσία φιλοξενίας. Διαφορετικά, θα εκτεθείτε σε
σημαντικούς κινδύνους ασφαλείας. Θα ήταν σαν να ζείτε σε ένα
διαμέρισμα όπου η μπροστινή πόρτα δεν μπορεί να κλείσει και είναι
πάντα ορθάνοιχτη.
Πώς να διαμορφώσετε έναν διακομιστή για ωραίες διευθύνσεις 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
βρίσκεται στον κατάλογο document-root (δηλ. δίπλα στο αρχείο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 δεν είναι ενεργοποιημένο. Υπάρχουν διάφοροι τρόποι για να το
ενεργοποιήσετε. Ανατρέξτε στο Stack Overflow για διάφορους τρόπους που
μπορεί να γίνει αυτό σε διαφορετικές ρυθμίσεις.
Οι σύνδεσμοι δημιουργούνται χωρίς το
https:
Η Nette παράγει συνδέσμους με το ίδιο πρωτόκολλο που χρησιμοποιεί η
τρέχουσα σελίδα. Έτσι, στη σελίδα https://foo
και αντίστροφα. Αν
βρίσκεστε πίσω από έναν αντίστροφο διακομιστή μεσολάβησης που
απογυμνώνει το HTTPS (για παράδειγμα, στο Docker), τότε πρέπει να ρυθμίσετε έναν διακομιστή μεσολάβησης στις
ρυθμίσεις για να λειτουργήσει σωστά η ανίχνευση πρωτοκόλλου.
Αν χρησιμοποιείτε το 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 or hostname of the server/container where the application is running
}
Στη συνέχεια, πρέπει να καθορίσετε το διακομιστή μεσολάβησης IP και, αν ισχύει, την περιοχή IP του τοπικού σας δικτύου όπου εκτελείτε την υποδομή:
http:
proxy: IP-proxy/IP-range
Χρήση των χαρακτήρων { } στη JavaScript
Οι χαρακτήρες {
and }
χρησιμοποιούνται για τη συγγραφή
ετικετών Latte. Ό,τι (εκτός από το κενό και τα εισαγωγικά) ακολουθεί το
{
character is considered a tag. If you need to print character {
(συχνά στη JavaScript),
μπορείτε να βάλετε ένα κενό (ή άλλο κενό χαρακτήρα) αμέσως μετά το
{
. Με αυτόν τον τρόπο αποφεύγετε την ερμηνεία του ως ετικέτα.
Αν είναι απαραίτητο να εκτυπώσετε αυτούς τους χαρακτήρες σε μια
κατάσταση όπου θα ερμηνεύονταν ως ετικέτα, μπορείτε να
χρησιμοποιήσετε ειδικές ετικέτες για να εκτυπώσετε αυτούς τους
χαρακτήρες – {l}
για {
and {r}
για }
.
{is tag}
{ is not tag }
{l}is not tag{r}
Σημείωση Presenter::getContext() is deprecated
Το Nette είναι μακράν το πρώτο πλαίσιο PHP που πέρασε στην έγχυση
εξαρτήσεων και οδήγησε τους προγραμματιστές να το χρησιμοποιούν με
συνέπεια, ξεκινώντας από τους παρουσιαστές. Αν ένας παρουσιαστής
χρειάζεται μια εξάρτηση, θα τη
ζητήσει. Αντίθετα, ο τρόπος με τον οποίο περνάμε ολόκληρο το DI container
σε μια κλάση και αυτή αντλεί τις εξαρτήσεις από αυτήν απευθείας
θεωρείται αντιπρότυπο (ονομάζεται service locator). Αυτός ο τρόπος
χρησιμοποιήθηκε στη Nette 0.x πριν από την έλευση του dependency injection, και
κατάλοιπό του είναι η μέθοδος Presenter::getContext()
, που έχει
χαρακτηριστεί προ πολλού ως απαρχαιωμένη.
Αν μεταφέρετε μια πολύ παλιά εφαρμογή Nette, μπορεί να διαπιστώσετε ότι
εξακολουθεί να χρησιμοποιεί αυτή τη μέθοδο. Έτσι, από την έκδοση 3.1 του
nette/application
θα συναντήσετε την προειδοποίηση
Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection
, από την έκδοση
4.0 θα συναντήσετε το σφάλμα ότι η μέθοδος δεν υπάρχει.
Η καθαρή λύση, φυσικά, είναι να επανασχεδιάσετε την εφαρμογή ώστε να
περνάει εξαρτήσεις χρησιμοποιώντας dependency injection. Ως εναλλακτική λύση,
μπορείτε να προσθέσετε τη δική σας μέθοδο 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;
}
}