Bootstrap
Bootstrap este codul de pornire care inițializează mediul, creează un container de injecție a dependențelor (DI) și pornește aplicația. Vom discuta despre:
- cum să vă configurați aplicația utilizând fișiere NEON
- cum să gestionați modurile de producție și de dezvoltare
- cum să creați containerul DI
Aplicațiile, fie că sunt bazate pe web sau scripturi în linie de comandă, încep printr-o anumită formă de inițializare
a mediului. În vremurile vechi, putea fi un fișier numit eg include.inc.php
care se ocupa de acest lucru și care
era inclus în fișierul inițial. În aplicațiile moderne Nette, acesta a fost înlocuit de clasa Bootstrap
, care,
ca parte a aplicației, poate fi găsită în fișierul app/Bootstrap.php
. Acesta ar putea arăta de exemplu
astfel:
use Nette\Bootstrap\Configurator;
class Bootstrap
{
private Configurator $configurator;
private string $rootDir;
public function __construct()
{
$this->rootDir = dirname(__DIR__);
// Configuratorul este responsabil de configurarea mediului și a serviciilor aplicației.
$this->configurator = new Configurator;
// Setați directorul pentru fișierele temporare generate de Nette (de exemplu, șabloane compilate)
$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 este inteligent, iar modul de dezvoltare se activează automat,
// sau îl puteți activa pentru o anumită adresă IP prin decomentarea următoarei linii:
// $this->configurator->setDebugMode('secret@23.75.345.200');
// Activează Tracy: instrumentul suprem de depanare "swiss army knife".
$this->configurator->enableTracy($this->rootDir . '/log');
// RobotLoader: Încarcă automat toate clasele din directorul dat
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
}
private function setupContainer(): void
{
// Încarcă fișierele de configurare
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
}
}
index.php
Fișierul inițial pentru aplicațiile web este index.php
, situat în directorul public www/
. Acesta
utilizează clasa Bootstrap
pentru a inițializa mediul și a crea un container DI. Apoi, obține serviciul
Application
din container, care lansează aplicația web:
$bootstrap = new App\Bootstrap;
// Inițializarea mediului + crearea unui container DI
$container = $bootstrap->bootWebApplication();
// Containerul DI creează un obiect Nette\Application\Application
$application = $container->getByType(Nette\Application\Application::class);
// Porniți aplicația Nette și tratați cererea de intrare
$application->run();
După cum puteți vedea, clasa Nette\Bootstrap\Configurator, pe care o vom prezenta acum mai în detaliu, ajută la configurarea mediului și la crearea unui container de injecție a dependențelor (DI).
Modul de dezvoltare vs. modul de producție
Nette face distincție între două moduri de bază în care este executată o cerere: dezvoltare și producție. Modul de dezvoltare este axat pe confortul maxim al programatorului, Tracy este afișat, memoria cache este actualizată automat atunci când se schimbă șabloanele sau configurația containerului DI etc. Modul de producție este axat pe performanță, Tracy înregistrează doar erorile, iar modificările șabloanelor și ale altor fișiere nu sunt verificate.
Selectarea modului se face prin autodetecție, astfel încât, de obicei, nu este nevoie să configurați sau să comutați
nimic manual. Modul este dezvoltare dacă aplicația rulează pe localhost (adică adresa IP 127.0.0.1
sau
::1
) și nu este prezent niciun proxy (adică antetul său HTTP). În caz contrar, se execută în modul de
producție.
Dacă doriți să activați modul de dezvoltare în alte cazuri, de exemplu, pentru programatorii care accesează de la
o anumită adresă IP, puteți utiliza setDebugMode()
:
$this->configurator->setDebugMode('23.75.345.200'); // una sau mai multe adrese IP
Vă recomandăm cu siguranță să combinați o adresă IP cu un cookie. Vom stoca un token secret în cookie-ul
nette-debug
, de exemplu secret1234
, iar modul de dezvoltare va fi activat pentru programatorii cu
această combinație de IP și cookie.
$this->configurator->setDebugMode('secret1234@23.75.345.200');
De asemenea, putem dezactiva complet modul de dezvoltare, chiar și pentru localhost:
$this->configurator->setDebugMode(false);
Rețineți că valoarea true
activează modul dezvoltator din greu, ceea ce nu ar trebui să se întâmple
niciodată pe un server de producție.
Instrumentul de depanare Tracy
Pentru o depanare mai ușoară, vom porni minunata unealtă Tracy. În modul dezvoltator, acesta vizualizează erorile, iar în modul de producție înregistrează erorile în directorul specificat:
$this->configurator->enableTracy($this->rootDir . '/log');
Temporary Files
Nette utilizează memoria cache pentru DI container, RobotLoader, șabloane etc. Prin urmare, este necesar să setați calea către directorul în care va fi stocată memoria cache:
$this->configurator->setTempDirectory($this->rootDir . '/temp');
Pe Linux sau macOS, setați permisiunile
de scriere pentru directoarele log/
și temp/
.
RobotLoader
De obicei, vom dori să încărcăm automat clasele folosind RobotLoader, așa că trebuie să
îl pornim și să îl lăsăm să încarce clasele din directorul în care se află Bootstrap.php
(adică
__DIR__
) și din toate subdirectoarele sale:
$this->configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
O modalitate alternativă este de a utiliza doar încărcarea automată Composer PSR-4.
Fusul orar
Configurator vă permite să specificați un fus orar pentru aplicația dumneavoastră.
$this->configurator->setTimeZone('Europe/Prague');
Configurarea containerului DI
O parte a procesului de pornire constă în crearea unui container DI, adică a unei fabrici de obiecte, care reprezintă inima întregii aplicații. Acesta este de fapt o clasă PHP generată de Nette și stocată într-un director de cache. Fabrica produce obiectele cheie ale aplicației, iar fișierele de configurare o instruiesc cum să le creeze și să le configureze și, astfel, influențăm comportamentul întregii aplicații.
Fișierele de configurare sunt de obicei scrise în formatul NEON. Puteți citi ce poate fi configurat aici.
În modul de dezvoltare, containerul este actualizat automat de fiecare dată când modificați codul sau fișierele de configurare. În modul de producție, acesta este generat o singură dată, iar modificările fișierelor nu sunt verificate pentru a maximiza performanța.
Fișierele de configurare sunt încărcate utilizând addConfig()
:
$this->configurator->addConfig($this->rootDir . '/config/common.neon');
Metoda addConfig()
poate fi apelată de mai multe ori pentru a adăuga mai multe fișiere.
$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');
}
Numele cli.php
nu este o greșeală de tipar, deoarece configurația poate fi scrisă și într-un fișier PHP,
care o returnează sub forma unei matrice.
Alternativ, putem folosi secțiuneaincludes
pentru a încărca mai multe
fișiere de configurare.
Dacă în fișierele de configurare apar elemente cu aceleași chei în cadrul fișierelor de configurare, acestea vor fi suprascrise sau fuzionate în cazul array-urilor. Ultimul fișier
inclus are o prioritate mai mare decât cel anterior. Fișierul în care este listată secțiunea includes
are
o prioritate mai mare decât fișierele incluse în el.
Parametrii statici
Parametrii utilizați în fișierele de configurare pot fi definiți în secțiunea parameters
și, de asemenea, pot fi
trecuți (sau suprascriși) prin metoda addStaticParameters()
(are pseudonimul addParameters()
). Este
important ca valorile diferite ale parametrilor să determine generarea de containere DI suplimentare, adică de clase
suplimentare.
$this->configurator->addStaticParameters([
'projectId' => 23,
]);
În fișierele de configurare, putem scrie notația obișnuită %projectId%
pentru a accesa parametrul numit
projectId
.
Parametrii dinamici
De asemenea, putem adăuga parametri dinamici la container, valorile lor diferite, spre deosebire de parametrii statici, nu vor determina generarea de noi containere DI.
$this->configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
Variabilele de mediu ar putea fi puse cu ușurință la dispoziție prin intermediul parametrilor dinamici. Le putem accesa
prin intermediul %env.variable%
în fișierele de configurare.
$this->configurator->addDynamicParameters([
'env' => getenv(),
]);
Parametrii impliciți
Puteți utiliza următorii parametri statici în fișierele de configurare:
%appDir%
este calea absolută către directorul fișieruluiBootstrap.php
%wwwDir%
este calea absolută către directorul care conține fișierul de intrareindex.php
%tempDir%
este calea absolută către directorul pentru fișierele temporare%vendorDir%
este calea absolută către directorul în care Composer instalează bibliotecile%rootDir%
este calea absolută către directorul rădăcină al proiectului%debugMode%
indică dacă aplicația se află în modul de depanare%consoleMode%
indică dacă cererea a venit prin linia de comandă
Servicii importate
Acum mergem mai departe. Deși scopul unui container DI este acela de a crea obiecte, în mod excepțional poate fi nevoie să
se introducă un obiect existent în container. Facem acest lucru prin definirea serviciului cu atributul
imported: true
.
services:
myservice:
type: App\Model\MyCustomService
imported: true
Creați o nouă instanță și inserați-o în bootstrap:
$this->configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);
Diferite medii
Nu ezitați să personalizați clasa Bootstrap
în funcție de nevoile dumneavoastră. Puteți adăuga parametri
la metoda bootWebApplication()
pentru a face diferența între proiectele web. Alternativ, puteți adăuga alte
metode, cum ar fi bootTestEnvironment()
pentru a inițializa mediul pentru testele unitare,
bootConsoleApplication()
pentru scripturile apelate din linia de comandă și așa mai departe.
public function bootTestEnvironment(): Nette\DI\Container
{
Tester\Environment::setup(); // Inițializarea 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();
}