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 se comportă diferit în funcție de faptul dacă rulează pe un server de dezvoltare sau de producție:

🛠️ Modul de dezvoltare
Afișează bara de depanare Tracy cu informații utile (de exemplu, interogări SQL, timp de execuție, utilizarea memoriei).
Afișează o pagină de erori detaliată cu urmele apelurilor funcțiilor și conținutul variabilelor atunci când apare o eroare.
Actualizează automat memoria cache atunci când sunt modificate șabloanele Latte, fișierele de configurare etc.
🚀 Modul de producție
Nu afișează nicio informație de depanare; toate erorile sunt înregistrate.
Afișează o pagină ErrorPresenter sau o pagină generică “Server Error” atunci când apare o eroare.
Cache-ul nu este niciodată reîmprospătat automat!
Optimizat pentru viteză și securitate.

Modul este determinat automat, astfel încât, în majoritatea cazurilor, nu este nevoie să îl configurați sau să îl comutați manual:

  • Modul de dezvoltare: Activ pe localhost (adresa IP 127.0.0.1 sau ::1), cu excepția cazului în care se utilizează un proxy (adică, pe baza antetelor sale HTTP).
  • Modul de producție: Activ peste tot.

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șierului Bootstrap.php
  • %wwwDir% este calea absolută către directorul care conține fișierul de intrare index.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();
}
versiune: 4.0