Bootstrap
Το Bootstrap είναι ο κώδικας εκκίνησης που αρχικοποιεί το περιβάλλον, δημιουργεί ένα δοχείο έγχυσης εξαρτήσεων (DI) και εκκινεί την εφαρμογή. Θα συζητήσουμε:
- πώς να ρυθμίσετε την εφαρμογή σας χρησιμοποιώντας αρχεία NEON
- πώς να χειρίζεστε τις λειτουργίες παραγωγής και ανάπτυξης
- πώς να δημιουργήσετε το δοχείο DI
Οι εφαρμογές, είτε βασίζονται στο διαδίκτυο είτε σε σενάρια γραμμής
εντολών, ξεκινούν με κάποια μορφή αρχικοποίησης του περιβάλλοντος.
Στην αρχαιότητα, θα μπορούσε να είναι ένα αρχείο με το όνομα eg
include.inc.php
που ήταν υπεύθυνο γι' αυτό και συμπεριλαμβανόταν στο
αρχικό αρχείο. Στις σύγχρονες εφαρμογές Nette, έχει αντικατασταθεί από
την κλάση Bootstrap
, η οποία ως μέρος της εφαρμογής μπορεί να βρεθεί
στο app/Bootstrap.php
. Μπορεί να μοιάζει για παράδειγμα ως εξής:
use Nette\Bootstrap\Configurator;
class Bootstrap
{
private Configurator $configurator;
private string $rootDir;
public function __construct()
{
$this->rootDir = dirname(__DIR__);
// Ο διαμορφωτής είναι υπεύθυνος για τη ρύθμιση του περιβάλλοντος και των υπηρεσιών της εφαρμογής.
$this->configurator = new Configurator;
// Ορίστε τον κατάλογο για τα προσωρινά αρχεία που παράγονται από τη Nette (π.χ. μεταγλωττισμένα πρότυπα)
$this->configurator->setTempDirectory($this->rootDir . '/temp');
}
public function bootWebApplication(): Nette\DI\Container
{
$this->initializeEnvironment();
$this->setupContainer();
return $this->configurator->createContainer();
}
private function initializeEnvironment(): void
{
// Η Nette είναι έξυπνη και η λειτουργία ανάπτυξης ενεργοποιείται αυτόματα,
// ή μπορείτε να την ενεργοποιήσετε για μια συγκεκριμένη διεύθυνση IP ξεσχολιάζοντας την ακόλουθη γραμμή:
// $this->configurator->setDebugMode('secret@23.75.345.200'),
// Ενεργοποιεί το Tracy: το απόλυτο εργαλείο αποσφαλμάτωσης "ελβετικό μαχαίρι του στρατού".
$this->configurator->enableTracy($this->rootDir . '/log');
// RobotLoader: αυτόματη φόρτωση όλων των κλάσεων στον δεδομένο κατάλογο
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
}
private function setupContainer(): void
{
// Φόρτωση αρχείων διαμόρφωσης
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
}
}
index.php
Το αρχικό αρχείο για τις διαδικτυακές εφαρμογές είναι το
index.php
, το οποίο βρίσκεται στον δημόσιο κατάλογο www/
.
Χρησιμοποιεί την κλάση Bootstrap
για την αρχικοποίηση του
περιβάλλοντος και τη δημιουργία ενός δοχείου DI. Στη συνέχεια, λαμβάνει
την υπηρεσία Application
από το δοχείο, η οποία εκκινεί την
εφαρμογή ιστού:
$bootstrap = new App\Bootstrap;
// Αρχικοποίηση του περιβάλλοντος + δημιουργία ενός δοχείου DI
$container = $bootstrap->bootWebApplication();
// Το δοχείο DI δημιουργεί ένα αντικείμενο Nette\Application\Application
$application = $container->getByType(Nette\Application\Application::class);
// Εκκίνηση της εφαρμογής Nette και χειρισμός της εισερχόμενης αίτησης
$application->run();
Όπως βλέπετε, η κλάση Nette\Bootstrap\Configurator, την οποία θα παρουσιάσουμε τώρα με περισσότερες λεπτομέρειες, βοηθάει στη ρύθμιση του περιβάλλοντος και στη δημιουργία ενός δοχείου έγχυσης εξαρτήσεων (DI).
Λειτουργία ανάπτυξης έναντι λειτουργίας παραγωγής
Η Nette διακρίνει μεταξύ δύο βασικών τρόπων εκτέλεσης μιας αίτησης: ανάπτυξη και παραγωγή. Η λειτουργία ανάπτυξης επικεντρώνεται στη μέγιστη άνεση του προγραμματιστή, εμφανίζεται το Tracy, η προσωρινή μνήμη ενημερώνεται αυτόματα όταν αλλάζουν τα πρότυπα ή η διαμόρφωση του DI container, κ.λπ. Η λειτουργία παραγωγής επικεντρώνεται στην απόδοση, το Tracy καταγράφει μόνο τα σφάλματα και δεν ελέγχονται οι αλλαγές των προτύπων και άλλων αρχείων.
Η επιλογή της λειτουργίας γίνεται με αυτόματη ανίχνευση, οπότε
συνήθως δεν χρειάζεται να ρυθμίσετε ή να αλλάξετε κάτι χειροκίνητα. Η
κατάσταση λειτουργίας είναι development εάν η εφαρμογή εκτελείται στο localhost
(δηλαδή στη διεύθυνση IP 127.0.0.1
ή ::1
) και δεν υπάρχει proxy
(δηλαδή η επικεφαλίδα HTTP του). Διαφορετικά, εκτελείται σε κατάσταση
παραγωγής.
Αν θέλετε να ενεργοποιήσετε τη λειτουργία ανάπτυξης σε άλλες
περιπτώσεις, για παράδειγμα, για προγραμματιστές που έχουν πρόσβαση
από μια συγκεκριμένη διεύθυνση IP, μπορείτε να χρησιμοποιήσετε τη
διεύθυνση setDebugMode()
:
$this->configurator->setDebugMode('23.75.345.200'); // μία ή περισσότερες διευθύνσεις IP
Συνιστούμε οπωσδήποτε τον συνδυασμό μιας διεύθυνσης IP με ένα cookie. Θα
αποθηκεύσουμε ένα μυστικό token στο cookie nette-debug
, π.χ. secret1234
,
και η λειτουργία ανάπτυξης θα ενεργοποιηθεί για τους προγραμματιστές
με αυτόν τον συνδυασμό IP και cookie.
$this->configurator->setDebugMode('secret1234@23.75.345.200');
Μπορούμε επίσης να απενεργοποιήσουμε εντελώς τη λειτουργία προγραμματιστή, ακόμη και για το localhost:
$this->configurator->setDebugMode(false);
Σημειώστε ότι η τιμή true
ενεργοποιεί τη λειτουργία
προγραμματιστή με σκληρό τρόπο, κάτι που δεν πρέπει ποτέ να συμβαίνει
σε έναν διακομιστή παραγωγής.
Εργαλείο εντοπισμού σφαλμάτων Tracy
Για εύκολη αποσφαλμάτωση, θα ενεργοποιήσουμε το σπουδαίο εργαλείο Tracy. Στη λειτουργία προγραμματιστή απεικονίζει τα σφάλματα και στη λειτουργία παραγωγής καταγράφει τα σφάλματα στον καθορισμένο κατάλογο:
$this->configurator->enableTracy($this->rootDir . '/log');
Προσωρινά αρχεία
Η Nette χρησιμοποιεί την κρυφή μνήμη για το DI container, το RobotLoader, τα πρότυπα κ.λπ. Ως εκ τούτου, είναι απαραίτητο να ορίσετε τη διαδρομή προς τον κατάλογο όπου θα αποθηκεύεται η προσωρινή μνήμη:
$this->configurator->setTempDirectory($this->rootDir . '/temp');
Σε Linux ή macOS, ορίστε τα δικαιώματα εγγραφής για
τους καταλόγους log/
και temp/
.
RobotLoader
Συνήθως, θα θέλουμε να φορτώνουμε αυτόματα τις κλάσεις
χρησιμοποιώντας τον RobotLoader, οπότε πρέπει
να τον εκκινήσουμε και να τον αφήσουμε να φορτώσει κλάσεις από τον
κατάλογο όπου βρίσκεται το Bootstrap.php
(δηλαδή το __DIR__
) και
όλους τους υποκαταλόγους του:
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
Ένας εναλλακτικός τρόπος είναι να χρησιμοποιήσετε μόνο την αυτόματη φόρτωση του Composer PSR-4.
Χρονοζώνη
Το Configurator σας επιτρέπει να καθορίσετε μια ζώνη ώρας για την εφαρμογή σας.
$this->configurator->setTimeZone('Europe/Prague');
Διαμόρφωση εμπορευματοκιβωτίων DI
Μέρος της διαδικασίας εκκίνησης είναι η δημιουργία ενός DI container, δηλαδή ενός εργοστασίου για αντικείμενα, το οποίο αποτελεί την καρδιά ολόκληρης της εφαρμογής. Πρόκειται στην πραγματικότητα για μια κλάση PHP που παράγεται από τη Nette και αποθηκεύεται σε έναν κατάλογο cache. Το εργοστάσιο παράγει βασικά αντικείμενα της εφαρμογής και τα αρχεία διαμόρφωσης του δίνουν οδηγίες για το πώς να τα δημιουργεί και να τα διαμορφώνει, και έτσι επηρεάζουμε τη συμπεριφορά ολόκληρης της εφαρμογής.
Τα αρχεία διαμόρφωσης γράφονται συνήθως σε μορφή NEON. Μπορείτε να διαβάσετε τι μπορεί να ρυθμιστεί εδώ.
Στη λειτουργία ανάπτυξης, ο περιέκτης ενημερώνεται αυτόματα κάθε φορά που αλλάζετε τον κώδικα ή τα αρχεία διαμόρφωσης. Στη λειτουργία παραγωγής, δημιουργείται μόνο μία φορά και οι αλλαγές αρχείων δεν ελέγχονται για να μεγιστοποιηθεί η απόδοση.
Τα αρχεία διαμόρφωσης φορτώνονται με τη χρήση του addConfig()
:
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
Η μέθοδος addConfig()
μπορεί να κληθεί πολλές φορές για την
προσθήκη πολλών αρχείων.
$configDir = $this->rootDir . '/config';
$this->configurator->addConfig($configDir . '/common.neon');
$this->configurator->addConfig($configDir . '/services.neon');
if (PHP_SAPI === 'cli') {
$this->configurator->addConfig($configDir . '/cli.php');
}
Το όνομα cli.php
δεν είναι τυπογραφικό λάθος, η διαμόρφωση μπορεί
επίσης να γραφτεί σε ένα αρχείο PHP, το οποίο την επιστρέφει ως πίνακα.
Εναλλακτικά, μπορούμε να χρησιμοποιήσουμε το τμήμαincludes
για
να φορτώσουμε περισσότερα αρχεία ρυθμίσεων.
Εάν στοιχεία με τα ίδια κλειδιά εμφανίζονται μέσα σε αρχεία
διαμόρφωσης, θα αντικατασταθούν ή θα
συγχωνευθούν στην περίπτωση των πινάκων. Το αρχείο που
περιλαμβάνεται αργότερα έχει υψηλότερη προτεραιότητα από το
προηγούμενο. Το αρχείο στο οποίο παρατίθεται το τμήμα includes
έχει
υψηλότερη προτεραιότητα από τα αρχεία που περιλαμβάνονται σε αυτό.
Στατικές παράμετροι
Οι παράμετροι που χρησιμοποιούνται σε αρχεία ρυθμίσεων μπορούν να
οριστούν στην ενότητα
parameters
και επίσης να μεταβιβαστούν (ή να αντικατασταθούν) από
τη μέθοδο addStaticParameters()
(έχει το ψευδώνυμο addParameters()
). Είναι
σημαντικό ότι διαφορετικές τιμές παραμέτρων προκαλούν τη δημιουργία
πρόσθετων δοχείων DI, δηλαδή πρόσθετων κλάσεων.
$this->configurator->addStaticParameters([
'projectId' => 23,
]);
Στα αρχεία ρυθμίσεων, μπορούμε να γράψουμε τον συνήθη συμβολισμό
%projectId%
για να αποκτήσουμε πρόσβαση στην παράμετρο με το όνομα
projectId
.
Δυναμικές παράμετροι
Μπορούμε επίσης να προσθέσουμε δυναμικές παραμέτρους στο δοχείο, οι διαφορετικές τιμές τους, σε αντίθεση με τις στατικές παραμέτρους, δεν θα προκαλέσουν τη δημιουργία νέων δοχείων DI.
$this->configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
Οι μεταβλητές περιβάλλοντος θα μπορούσαν εύκολα να γίνουν
διαθέσιμες με τη χρήση δυναμικών παραμέτρων. Μπορούμε να έχουμε
πρόσβαση σε αυτές μέσω της διεύθυνσης %env.variable%
στα αρχεία
ρυθμίσεων.
$this->configurator->addDynamicParameters([
'env' => getenv(),
]);
Προεπιλεγμένες παράμετροι
Μπορείτε να χρησιμοποιήσετε τις ακόλουθες στατικές παραμέτρους στα αρχεία διαμόρφωσης:
%appDir%
είναι η απόλυτη διαδρομή προς τον κατάλογο του αρχείουBootstrap.php
%wwwDir%
είναι η απόλυτη διαδρομή προς τον κατάλογο που περιέχει το αρχείο καταχώρησηςindex.php
%tempDir%
είναι η απόλυτη διαδρομή προς τον κατάλογο για τα προσωρινά αρχεία%vendorDir%
είναι η απόλυτη διαδρομή προς τον κατάλογο όπου ο Composer εγκαθιστά τις βιβλιοθήκες%rootDir%
είναι η απόλυτη διαδρομή προς τον ριζικό κατάλογο του έργου- Το
%debugMode%
δηλώνει αν η εφαρμογή βρίσκεται σε κατάσταση αποσφαλμάτωσης. - Το
%consoleMode%
δηλώνει αν η αίτηση υποβλήθηκε μέσω της γραμμής εντολών.
Εισαγόμενες υπηρεσίες
Πάμε πιο βαθιά τώρα. Παρόλο που ο σκοπός ενός DI container είναι η
δημιουργία αντικειμένων, κατ' εξαίρεση μπορεί να υπάρξει ανάγκη
εισαγωγής ενός υπάρχοντος αντικειμένου στο container. Αυτό το κάνουμε
ορίζοντας την υπηρεσία με το χαρακτηριστικό imported: true
.
services:
myservice:
type: App\Model\MyCustomService
imported: true
Δημιουργούμε μια νέα περίπτωση και την εισάγουμε στο bootstrap:
$this->configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);
Διαφορετικά περιβάλλοντα
Μη διστάσετε να προσαρμόσετε την τάξη Bootstrap
σύμφωνα με τις
ανάγκες σας. Μπορείτε να προσθέσετε παραμέτρους στη μέθοδο
bootWebApplication()
για να διαφοροποιήσετε τα διάφορα web projects.
Εναλλακτικά, μπορείτε να προσθέσετε άλλες μεθόδους, όπως
bootTestEnvironment()
για την αρχικοποίηση του περιβάλλοντος για δοκιμές
μονάδας, bootConsoleApplication()
για σενάρια που καλούνται από τη γραμμή
εντολών κ.ο.κ.
public function bootTestEnvironment(): Nette\DI\Container
{
Tester\Environment::setup(); // Αρχικοποίηση Nette Tester
$this->setupContainer();
return $this->configurator->createContainer();
}
public function bootConsoleApplication(): Nette\DI\Container
{
$this->configurator->setDebugMode(false);
$this->initializeEnvironment();
$this->setupContainer();
return $this->configurator->createContainer();
}