Πώς λειτουργούν οι εφαρμογές;

Αυτή τη στιγμή διαβάζετε το βασικό έγγραφο της τεκμηρίωσης της Nette. Θα μάθετε όλες τις αρχές των διαδικτυακών εφαρμογών. Νίκαια από το Α έως το Ω, από τη στιγμή της γέννησης μέχρι την τελευταία ανάσα του PHP script. Μετά την ανάγνωση θα γνωρίζετε:

  • πώς λειτουργούν όλα
  • τι είναι το Bootstrap, ο Presenter και το DI container
  • πώς είναι η δομή των καταλόγων

Δομή καταλόγου

Ανοίξτε ένα παράδειγμα ενός σκελετού μιας διαδικτυακής εφαρμογής που ονομάζεται WebProject και μπορείτε να παρακολουθήσετε τα αρχεία που γράφονται.

Η δομή του καταλόγου μοιάζει κάπως έτσι:

web-project/
├── app/                      ← directory with application
│   ├── Core/                 ← βασικές αναγκαίες τάξεις
│   │   └── RouterFactory.php ← διαμόρφωση των διευθύνσεων URL
│   ├── UI/                   ← παρουσιαστές, πρότυπα και λοιπά.
│   │   ├── @layout.latte     ← πρότυπο κοινής διάταξης
│   │   └── Home/             ← Αρχικός κατάλογος παρουσιαστών
│   │       ├── HomePresenter.php ← Κλάση οικιακού παρουσιαστή
│   │       └── default.latte ← πρότυπο για τη δράση default
│   └── Bootstrap.php         ← booting class Bootstrap
├── bin/                      ← scripts for the command line
├── config/                   ← configuration files
│   ├── common.neon
│   └── services.neon
├── log/                      ← error logs
├── temp/                     ← temporary files, cache, …
├── vendor/                   ← libraries installed by Composer
│   ├── ...
│   └── autoload.php          ← autoloading of libs installed by Composer
├── www/                      ← public directory, document root of project
│   ├── .htaccess             ← mod_rewrite rules etc
│   └── index.php             ← initial file that launches the application
└── .htaccess                 ← prohibits access to all directories except www

Μπορείτε να αλλάξετε τη δομή του καταλόγου με οποιονδήποτε τρόπο, να μετονομάσετε ή να μετακινήσετε φακέλους και στη συνέχεια να επεξεργαστείτε απλώς τις διαδρομές προς τα log/ και temp/ στο αρχείο Bootstrap.php και τη διαδρομή προς αυτό το αρχείο στο composer.json στο τμήμα autoload. Τίποτα περισσότερο, καμία περίπλοκη αναδιαμόρφωση, καμία συνεχής αλλαγή. Το Nette διαθέτει μια έξυπνη αυτόματη αναγνώριση.

Για λίγο μεγαλύτερες εφαρμογές, μπορούμε να χωρίσουμε τους φακέλους με τους παρουσιαστές και τα πρότυπα σε υποκαταλόγους (στο δίσκο) και σε χώρους ονομάτων (στον κώδικα), τους οποίους ονομάζουμε ενότητες.

Ο κατάλογος www/ είναι ο δημόσιος κατάλογος ή το document-root του έργου. Μπορείτε να τον μετονομάσετε χωρίς να χρειάζεται να ορίσετε κάτι άλλο στην πλευρά της εφαρμογής. Απλά πρέπει να ρυθμίσετε τη φιλοξενία έτσι ώστε το document-root να πηγαίνει σε αυτόν τον κατάλογο.

Μπορείτε επίσης να κατεβάσετε απευθείας το WebProject, συμπεριλαμβανομένου του Nette, χρησιμοποιώντας το Composer:

composer create-project nette/web-project

Στο Linux ή το macOS, ορίστε τα δικαιώματα εγγραφής για τους καταλόγους log/ και temp/.

Η εφαρμογή WebProject είναι έτοιμη να εκτελεστεί, δεν χρειάζεται να ρυθμίσετε τίποτε άλλο και μπορείτε να την δείτε απευθείας στο πρόγραμμα περιήγησης με πρόσβαση στο φάκελο www/.

Αίτημα HTTP

Όλα ξεκινούν όταν ένας χρήστης ανοίγει τη σελίδα σε ένα πρόγραμμα περιήγησης και το πρόγραμμα περιήγησης χτυπάει τον διακομιστή με ένα αίτημα HTTP. Το αίτημα πηγαίνει σε ένα αρχείο PHP που βρίσκεται στο δημόσιο κατάλογο www/, το οποίο είναι το index.php. Ας υποθέσουμε ότι πρόκειται για ένα αίτημα προς το https://example.com/product/123 και θα εκτελεστεί.

Η αποστολή του είναι η εξής:

  1. να αρχικοποιήσει το περιβάλλον
  2. να πάρει το εργοστάσιο
  3. να εκκινήσει την εφαρμογή Nette που χειρίζεται το αίτημα

Τι είδους εργοστάσιο; Δεν παράγουμε τρακτέρ, αλλά ιστοσελίδες! Περιμένετε, θα σας εξηγήσω αμέσως.

Με τον όρο “αρχικοποίηση του περιβάλλοντος” εννοούμε, για παράδειγμα, ότι ενεργοποιείται το Tracy, το οποίο είναι ένα καταπληκτικό εργαλείο για την καταγραφή ή την οπτικοποίηση σφαλμάτων. Καταγράφει τα σφάλματα στον διακομιστή παραγωγής και τα εμφανίζει απευθείας στον διακομιστή ανάπτυξης. Επομένως, η αρχικοποίηση πρέπει επίσης να αποφασίσει αν ο ιστότοπος εκτελείται σε κατάσταση παραγωγής ή ανάπτυξης. Για να το κάνει αυτό, η Nette χρησιμοποιεί αυτόματη ανίχνευση: αν τρέξετε τον ιστότοπο στο localhost, τρέχει σε λειτουργία προγραμματιστή. Δεν χρειάζεται να ρυθμίσετε τίποτα και η εφαρμογή είναι έτοιμη τόσο για ανάπτυξη όσο και για ανάπτυξη παραγωγής. Αυτά τα βήματα εκτελούνται και περιγράφονται λεπτομερώς στο κεφάλαιο σχετικά με την κλάση Bootstrap.

Το τρίτο σημείο (ναι, παραλείψαμε το δεύτερο, αλλά θα επανέλθουμε σε αυτό) είναι η εκκίνηση της εφαρμογής. Ο χειρισμός των αιτημάτων HTTP στη Nette γίνεται από την κλάση Nette\Application\Application (στο εξής θα αναφέρεται ως Application), οπότε όταν λέμε “τρέχουμε μια εφαρμογή”, εννοούμε να καλέσουμε μια μέθοδο με το όνομα run() σε ένα αντικείμενο αυτής της κλάσης.

Η Nette είναι ένας μέντορας που σας καθοδηγεί να γράψετε καθαρές εφαρμογές με αποδεδειγμένες μεθοδολογίες. Και η πιο αποδεδειγμένη ονομάζεται dependency injection, συντομογραφία DI. Προς το παρόν δεν θέλουμε να σας επιβαρύνουμε με την εξήγηση του DI, αφού υπάρχει ξεχωριστό κεφάλαιο, το σημαντικό εδώ είναι ότι τα βασικά αντικείμενα θα δημιουργούνται συνήθως από ένα εργοστάσιο για αντικείμενα που ονομάζεται DI container (συντομογραφία DIC). Ναι, αυτό είναι το εργοστάσιο που αναφέρθηκε πριν από λίγο καιρό. Και δημιουργεί επίσης το αντικείμενο Application για εμάς, οπότε χρειαζόμαστε πρώτα ένα δοχείο. Το παίρνουμε χρησιμοποιώντας την κλάση Configurator και το αφήνουμε να παράγει το αντικείμενο Application, καλούμε τη μέθοδο run() και έτσι ξεκινάει η εφαρμογή Nette. Αυτό ακριβώς συμβαίνει στο αρχείο index. php.

Εφαρμογή Nette

Η κλάση Application έχει ένα και μόνο καθήκον: να απαντά σε ένα αίτημα HTTP.

Οι εφαρμογές που γράφονται στο Nette χωρίζονται σε πολλούς λεγόμενους παρουσιαστές (σε άλλα πλαίσια μπορεί να συναντήσετε τον όρο ελεγκτής, που είναι ο ίδιος), οι οποίοι είναι κλάσεις που αντιπροσωπεύουν μια συγκεκριμένη σελίδα του ιστότοπου: π.χ. αρχική σελίδα, προϊόν στο ηλεκτρονικό κατάστημα, φόρμα εγγραφής, τροφοδοσία χάρτη σελίδων, κ.λπ. Η εφαρμογή μπορεί να έχει από έναν έως χιλιάδες παρουσιαστές.

Η εφαρμογή ξεκινά ζητώντας από τον λεγόμενο δρομολογητή να αποφασίσει ποιος από τους παρουσιαστές θα περάσει το τρέχον αίτημα για επεξεργασία. Ο δρομολογητής αποφασίζει ποιανού ευθύνη είναι. Κοιτάζει τη διεύθυνση URL εισόδου https://example.com/product/123, ο οποίος θέλει να show ένα προϊόν με id: 123 ως ενέργεια. Είναι καλή συνήθεια να γράφετε τα ζεύγη παρουσιαστής + δράση χωρισμένα με άνω και κάτω τελεία ως Product:show.

Έτσι, ο δρομολογητής μετατρέπει τη διεύθυνση URL σε ένα ζεύγος Presenter:action + παράμετροι, στην περίπτωσή μας Product:show + id: 123. Μπορείτε να δείτε πώς μοιάζει ένας δρομολογητής στο αρχείο app/Core/RouterFactory.php και θα τον περιγράψουμε αναλυτικά στο κεφάλαιο Δρομολόγηση.

Ας συνεχίσουμε. Η εφαρμογή γνωρίζει ήδη το όνομα του παρουσιαστή και μπορεί να συνεχίσει. Δημιουργώντας ένα αντικείμενο ProductPresenter, το οποίο είναι ο κώδικας του παρουσιαστή Product. Πιο συγκεκριμένα, ζητάει από το DI container τη δημιουργία του presenter, επειδή η παραγωγή αντικειμένων είναι η δουλειά του.

Ο παρουσιαστής μπορεί να μοιάζει ως εξής:

class ProductPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private ProductRepository $repository,
	) {
	}

	public function renderShow(int $id): void
	{
		// λαμβάνουμε δεδομένα από το μοντέλο και τα περνάμε στο πρότυπο
		$this->template->product = $this->repository->getProduct($id);
	}
}

Η αίτηση χειρίζεται από τον παρουσιαστή. Και η αποστολή είναι σαφής: κάντε την ενέργεια show με το id: 123. Το οποίο στη γλώσσα των παρουσιαστών σημαίνει ότι καλείται η μέθοδος renderShow() και στην παράμετρο $id παίρνει το 123.

Ένας παρουσιαστής μπορεί να χειριστεί πολλαπλές ενέργειες, δηλαδή να έχει πολλαπλές μεθόδους render<Action>(). Συνιστούμε όμως να σχεδιάζουμε παρουσιαστές με μία ή όσο το δυνατόν λιγότερες ενέργειες.

Έτσι, κλήθηκε η μέθοδος renderShow(123), της οποίας ο κώδικας είναι φανταστικό παράδειγμα, αλλά μπορείτε να δείτε σε αυτό πώς τα δεδομένα περνούν στο πρότυπο, δηλαδή με την εγγραφή στο $this->template.

Στη συνέχεια, ο παρουσιαστής επιστρέφει την απάντηση. Αυτό μπορεί να είναι μια σελίδα HTML, μια εικόνα, ένα έγγραφο XML, η αποστολή ενός αρχείου από το δίσκο, JSON ή η ανακατεύθυνση σε μια άλλη σελίδα. Σημαντικό είναι ότι, αν δεν πούμε ρητά πώς να απαντήσουμε (κάτι που συμβαίνει στην περίπτωση του ProductPresenter), η απάντηση θα είναι η απόδοση του προτύπου με μια σελίδα HTML. Γιατί; Λοιπόν, επειδή στο 99% των περιπτώσεων θέλουμε να σχεδιάσουμε ένα πρότυπο, οπότε ο παρουσιαστής θεωρεί αυτή τη συμπεριφορά ως προεπιλεγμένη και θέλει να διευκολύνει τη δουλειά μας. Αυτό είναι το νόημα της Nette.

Δεν χρειάζεται καν να καθορίσουμε ποιο πρότυπο θα αναπαραχθεί- το πλαίσιο θα βρει μόνο του τη διαδρομή. Στην περίπτωση της ενέργειας show, απλώς προσπαθεί να φορτώσει το πρότυπο show.latte στον κατάλογο με την κλάση ProductPresenter. Προσπαθεί επίσης να βρει τη διάταξη στο αρχείο @layout.latte (περισσότερα για την αναζήτηση προτύπων).

Στη συνέχεια, τα πρότυπα αποδίδονται. Με αυτόν τον τρόπο ολοκληρώνεται η εργασία του παρουσιαστή και ολόκληρης της εφαρμογής, και η εργασία έχει τελειώσει. Εάν το πρότυπο δεν υπήρχε, θα επιστρεφόταν μια σελίδα σφάλματος 404. Μπορείτε να διαβάσετε περισσότερα για τους παρουσιαστές στη σελίδα Παρουσιαστές.

Για να είμαστε σίγουροι, ας προσπαθήσουμε να ανακεφαλαιώσουμε την όλη διαδικασία με μια ελαφρώς διαφορετική διεύθυνση URL:

  1. η διεύθυνση URL θα είναι https://example.com
  2. εκκινούμε την εφαρμογή, δημιουργούμε έναν περιέκτη και εκτελούμε Application::run()
  3. ο δρομολογητής αποκωδικοποιεί τη διεύθυνση URL ως ζεύγος Home:default
  4. δημιουργείται ένα αντικείμενο HomePresenter
  5. καλείται η μέθοδος renderDefault() (αν υπάρχει)
  6. αποδίδεται ένα πρότυπο default.latte με διάταξη @layout.latte

Μπορεί να έχετε συναντήσει πολλές νέες έννοιες τώρα, αλλά πιστεύουμε ότι βγάζουν νόημα. Η δημιουργία εφαρμογών στη Nette είναι πανεύκολη.

Πρότυπα

Όσον αφορά τα πρότυπα, η Nette χρησιμοποιεί το σύστημα προτύπων Latte. Αυτός είναι ο λόγος για τον οποίο τα αρχεία με τα πρότυπα τελειώνουν με .latte. Το Latte χρησιμοποιείται επειδή είναι το πιο ασφαλές σύστημα προτύπων για την PHP και ταυτόχρονα το πιο διαισθητικό σύστημα. Δεν χρειάζεται να μάθετε πολλά καινούργια, αρκεί να γνωρίζετε την PHP και μερικές ετικέτες Latte. Θα μάθετε τα πάντα στην τεκμηρίωση.

Στο πρότυπο δημιουργούμε μια σύνδεση με άλλους παρουσιαστές & δράσεις ως εξής:

<a n:href="Product:show $productId">product detail</a>

Απλά γράψτε το γνωστό ζεύγος Presenter:action αντί της πραγματικής διεύθυνσης URL και συμπεριλάβετε τυχόν παραμέτρους. Το τέχνασμα είναι το n:href, το οποίο λέει ότι αυτό το χαρακτηριστικό θα επεξεργαστεί από τη Nette. Και θα δημιουργήσει:

<a href="/product/456">product detail</a>

Ο δρομολογητής που αναφέρθηκε προηγουμένως είναι υπεύθυνος για τη δημιουργία της διεύθυνσης URL. Στην πραγματικότητα, οι δρομολογητές στη Nette είναι μοναδικοί στο ότι μπορούν να εκτελέσουν όχι μόνο μετασχηματισμούς από μια διεύθυνση URL σε ένα ζεύγος παρουσιαστής:δράση, αλλά και αντίστροφα να δημιουργήσουν μια διεύθυνση URL από το όνομα του παρουσιαστή + δράση + παράμετροι. Χάρη σε αυτό, στη Nette μπορείτε να αλλάξετε εντελώς τη μορφή της διεύθυνσης URL σε ολόκληρη την ολοκληρωμένη εφαρμογή χωρίς να αλλάξετε ούτε έναν χαρακτήρα στο πρότυπο ή στον παρουσιαστή, απλώς τροποποιώντας τον δρομολογητή. Και χάρη σε αυτό, λειτουργεί το λεγόμενο canonization, το οποίο είναι ένα άλλο μοναδικό χαρακτηριστικό της Nette, το οποίο βελτιώνει το SEO (βελτιστοποίηση της δυνατότητας αναζήτησης στο διαδίκτυο) αποτρέποντας αυτόματα την ύπαρξη διπλού περιεχομένου σε διαφορετικές διευθύνσεις URL. Πολλοί προγραμματιστές το βρίσκουν εκπληκτικό αυτό.

Διαδραστικά στοιχεία

Έχουμε κάτι ακόμα να σας πούμε για τους παρουσιαστές: διαθέτουν ένα ενσωματωμένο σύστημα συστατικών. Οι παλαιότεροι από εσάς μπορεί να θυμάστε κάτι παρόμοιο από τους Delphi ή τις ASP.NET Web Forms. Το React ή το Vue.js είναι χτισμένο πάνω σε κάτι εξ αποστάσεως παρόμοιο. Στον κόσμο των πλαισίων PHP, αυτό είναι ένα εντελώς μοναδικό χαρακτηριστικό.

Τα συστατικά είναι ξεχωριστές επαναχρησιμοποιήσιμες μονάδες που τοποθετούμε σε σελίδες (δηλαδή παρουσιαστές). Μπορούν να είναι φόρμες, datagrids, μενού, δημοσκοπήσεις, στην πραγματικότητα οτιδήποτε έχει νόημα να χρησιμοποιείται επανειλημμένα. Μπορούμε να δημιουργήσουμε τα δικά μας συστατικά ή να χρησιμοποιήσουμε κάποιο από το τεράστιο φάσμα των συστατικών ανοιχτού κώδικα.

Τα συστατικά αλλάζουν ριζικά την προσέγγιση στην ανάπτυξη εφαρμογών. Θα ανοίξουν νέες δυνατότητες για τη σύνθεση σελίδων από προκαθορισμένες μονάδες. Και έχουν κάτι κοινό με το Χόλιγουντ.

Δοχείο DI και διαμόρφωση παραμέτρων

Το DI container (εργοστάσιο για αντικείμενα) είναι η καρδιά ολόκληρης της εφαρμογής.

Μην ανησυχείτε, δεν είναι ένα μαγικό μαύρο κουτί, όπως μπορεί να φαίνεται από τα προηγούμενα λόγια. Στην πραγματικότητα, είναι μια αρκετά βαρετή κλάση PHP που παράγεται από τη Nette και αποθηκεύεται σε έναν κατάλογο cache. Έχει πολλές μεθόδους που ονομάζονται createServiceAbcd() και κάθε μία από αυτές δημιουργεί και επιστρέφει ένα αντικείμενο. Ναι, υπάρχει επίσης μια μέθοδος createServiceApplication() που θα παράγει το Nette\Application\Application, το οποίο χρειαζόμασταν στο αρχείο index.php για να τρέξουμε την εφαρμογή. Και υπάρχουν μέθοδοι για την παραγωγή μεμονωμένων παρουσιαστών. Και ούτω καθεξής.

Τα αντικείμενα που δημιουργεί ο περιέκτης DI ονομάζονται υπηρεσίες για κάποιο λόγο.

Αυτό που είναι πραγματικά ιδιαίτερο σε αυτή την κλάση είναι ότι δεν προγραμματίζεται από εσάς, αλλά από το πλαίσιο. Στην πραγματικότητα παράγει τον κώδικα PHP και τον αποθηκεύει στο δίσκο. Εσείς απλώς δίνετε οδηγίες για το ποια αντικείμενα πρέπει να μπορεί να παράγει ο περιέκτης και πώς ακριβώς. Και αυτές οι οδηγίες γράφονται σε αρχεία ρυθμίσεων σε μορφή NEON και επομένως έχουν την επέκταση .neon.

Τα αρχεία ρυθμίσεων χρησιμοποιούνται καθαρά για την παροχή οδηγιών στον περιέκτη DI. Έτσι, για παράδειγμα, αν καθορίσω την επιλογή expiration: 14 days στο τμήμα session, ο DI container κατά τη δημιουργία του αντικειμένου Nette\Http\Session που αντιπροσωπεύει το session θα καλέσει τη μέθοδό του setExpiration('14 days'), και έτσι η διαμόρφωση γίνεται πραγματικότητα.

Υπάρχει ένα ολόκληρο κεφάλαιο έτοιμο για εσάς, που περιγράφει τι μπορεί να ρυθμιστεί και πώς να ορίσετε τις δικές σας υπηρεσίες.

Μόλις μπείτε στη δημιουργία υπηρεσιών, θα συναντήσετε τη λέξη autowiring. Πρόκειται για ένα gadget που θα κάνει τη ζωή σας απίστευτα πιο εύκολη. Μπορεί να μεταβιβάζει αυτόματα αντικείμενα όπου τα χρειάζεστε (στους κατασκευαστές των κλάσεών σας, για παράδειγμα) χωρίς να χρειάζεται να κάνετε τίποτα. Θα διαπιστώσετε ότι το δοχείο DI στη Nette είναι ένα μικρό θαύμα.

Τι θα γίνει στη συνέχεια;

Εξετάσαμε τις βασικές αρχές των εφαρμογών στη Nette. Μέχρι στιγμής, πολύ επιφανειακά, αλλά σύντομα θα εμβαθύνετε στα βάθη και τελικά θα δημιουργήσετε θαυμάσιες διαδικτυακές εφαρμογές. Πού να συνεχίσουμε; Έχετε δοκιμάσει το σεμινάριο Δημιουργία της πρώτης σας εφαρμογής;

Εκτός από τα παραπάνω, η Nette διαθέτει ένα ολόκληρο οπλοστάσιο χρήσιμων κλάσεων, στρώμα βάσης δεδομένων κ.λπ. Δοκιμάστε σκόπιμα να κάνετε απλώς κλικ μέσα από την τεκμηρίωση. Ή επισκεφθείτε το ιστολόγιο. Θα ανακαλύψετε πολλά ενδιαφέροντα πράγματα.

Αφήστε το πλαίσιο να σας φέρει πολλή χαρά 💙

έκδοση: 4.0