Bootstrap

A Bootstrap egy indító kód, amely inicializálja a környezetet, létrehoz egy függőségi injektálási (DI) konténert, és elindítja az alkalmazást. Megbeszéljük:

  • hogyan konfigurálhatja az alkalmazást NEON fájlok segítségével.
  • hogyan kezelje a termelési és a fejlesztési módokat
  • hogyan hozzuk létre a DI konténert

Az alkalmazások, akár webes alapúak, akár parancssori szkriptek, valamilyen környezet-inicializálással kezdődnek. A régi időkben ez egy pl. include.inc.php nevű fájl lehetett, amely ezért volt felelős, és a kezdeti fájlban szerepelt. A modern Nette alkalmazásokban ezt felváltotta a Bootstrap osztály, amely az alkalmazás részeként a app/Bootstrap.php. Ez például így nézhet ki:

use Nette\Bootstrap\Configurator;

class Bootstrap
{
	private Configurator $configurator;
	private string $rootDir;

	public function __construct()
	{
		$this->rootDir = dirname(__DIR__);
		// A konfigurátor felelős az alkalmazási környezet és a szolgáltatások beállításáért.
		$this->configurator = new Configurator;
		// A Nette által generált ideiglenes fájlok (pl. lefordított sablonok) könyvtárának beállítása.
		$this->configurator->setTempDirectory($this->rootDir . '/temp');
	}

	public function bootWebApplication(): Nette\DI\Container
	{
		$this->initializeEnvironment();
		$this->setupContainer();
		return $this->configurator->createContainer();
	}

	private function initializeEnvironment(): void
	{
		// A Nette intelligens, és a fejlesztői üzemmód automatikusan bekapcsol,
		// vagy engedélyezheti egy adott IP-címre a következő sor megjegyzésének feloldásával:
		// $this->configurator->setDebugMode('secret@23.75.345.200');

		// Bekapcsolja a Tracy-t: a végső "svájci bicska" hibakeresési eszköz.
		$this->configurator->enableTracy($this->rootDir . '/log');

		// RobotLoader: automatikusan feltölti az összes osztályt a megadott könyvtárban.
		$this->configurator->createRobotLoader()
			->addDirectory(__DIR__)
			->register();
	}

	private function setupContainer(): void
	{
		// Konfigurációs fájlok betöltése
		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
	}
}

index.php

A webes alkalmazások kezdőfájlja a index.php, amely a www/ nyilvános könyvtárban található. A Bootstrap osztályt használja a környezet inicializálásához és a DI konténer létrehozásához. Ezután megszerzi a Application szolgáltatást a konténerből, amely elindítja a webalkalmazást:

$bootstrap = new App\Bootstrap;
// A környezet inicializálása + DI konténer létrehozása
$container = $bootstrap->bootWebApplication();
// A DI konténer létrehoz egy Nette\Application\Application objektumot.
$application = $container->getByType(Nette\Application\Application::class);
// A Nette-alkalmazás elindítása és a bejövő kérések kezelése.
$application->run();

Mint látható, a Nette\Bootstrap\Configurator osztály, amelyet most részletesebben bemutatunk, segít a környezet beállításában és a függőségi injektálás (DI) konténer létrehozásában.

Fejlesztői vs. termelési üzemmód

A Nette másképp viselkedik attól függően, hogy fejlesztési vagy termelési szerveren fut:

🛠️ Fejlesztési mód
Megjeleníti a Tracy hibakereső sávot hasznos információkkal (pl. SQL-lekérdezések, végrehajtási idő, memóriahasználat).
Hiba esetén részletes hibalevelet jelenít meg függvényhívás nyomvonalakkal és változótartalommal.
Automatikusan frissíti a gyorsítótárat, amikor a Latte sablonok, konfigurációs fájlok stb. módosulnak.
🚀 Termelési mód
Nem jelenít meg semmilyen hibakeresési információt; minden hiba naplózásra kerül.
Hiba esetén megjelenít egy ErrorPresenter vagy egy általános “Szerverhiba” oldalt.
A gyorsítótár soha nem frissül automatikusan!
A sebességre és a biztonságra optimalizált.

Az üzemmódot automatikusan határozza meg, így a legtöbb esetben nincs szükség a manuális beállításra vagy váltásra:

  • Fejlesztési üzemmód: 127.0.0.1 vagy ::1), kivéve, ha proxy van használatban (azaz a HTTP fejlécek alapján).
  • Gyártási üzemmód: Mindenhol máshol aktív.

Ha más esetekben, például egy adott IP-címről hozzáférő programozók számára szeretné engedélyezni a fejlesztési üzemmódot, akkor a setDebugMode() címet használhatja:

$this->configurator->setDebugMode('23.75.345.200'); // egy vagy több IP-cím

Mindenképpen javasoljuk az IP-cím és a cookie kombinálását. A nette-debug cookie-ban tárolunk egy titkos tokent, pl. secret1234, és a fejlesztési mód az IP és a cookie ilyen kombinációjával rendelkező programozók számára aktiválódik.

$this->configurator->setDebugMode('secret1234@23.75.345.200');

A fejlesztői módot teljesen ki is kapcsolhatjuk, akár a localhost esetében is:

$this->configurator->setDebugMode(false);

A true érték keményen bekapcsolja a fejlesztői módot, ami soha nem történhet meg egy termelő szerveren.

Hibakereső eszköz Tracy

Az egyszerű hibakeresés érdekében bekapcsoljuk a Tracy nevű nagyszerű eszközt. Fejlesztői módban megjeleníti a hibákat, termelési módban pedig a megadott könyvtárba naplózza a hibákat:

$this->configurator->enableTracy($this->rootDir . '/log');

Ideiglenes fájlok

A Nette a DI konténer, a RobotLoader, a sablonok stb. számára használja a gyorsítótárat. Ezért szükséges annak a könyvtárnak az elérési útvonalát beállítani, ahol a gyorsítótár tárolásra kerül:

$this->configurator->setTempDirectory($this->rootDir . '/temp');

Linuxon vagy macOS-en állítsa be a log/ és a temp/ könyvtárak írási engedélyeit.

RobotLoader

Általában a RobotLoader segítségével szeretnénk automatikusan betölteni az osztályokat, ezért el kell indítanunk, és hagynunk kell, hogy betöltse az osztályokat abból a könyvtárból, ahol a Bootstrap.php található (azaz __DIR__) és annak összes alkönyvtárából:

$this->configurator->createRobotLoader()
	->addDirectory(__DIR__)
	->register();

Egy alternatív megoldás az, hogy csak a Composer PSR-4 automatikus betöltését használjuk.

Időzóna

A Configurator lehetővé teszi, hogy megadjon egy időzónát az alkalmazásához.

$this->configurator->setTimeZone('Europe/Prague');

DI konténer konfigurálása

Az indítási folyamat része a DI konténer, azaz az objektumgyár létrehozása, amely az egész alkalmazás szíve. Ez tulajdonképpen egy Nette által generált és egy cache könyvtárban tárolt PHP osztály. A gyár létrehozza az alkalmazás kulcsfontosságú objektumait, a konfigurációs fájlok pedig utasítják, hogyan hozza létre és konfigurálja őket, és így befolyásoljuk az egész alkalmazás viselkedését.

A konfigurációs fájlokat általában NEON formátumban írjuk. Itt olvashatja el, hogy mit lehet konfigurálni.

Fejlesztői üzemmódban a konténer automatikusan frissül minden alkalommal, amikor megváltoztatja a kódot vagy a konfigurációs fájlokat. Termelési módban csak egyszer generálódik, és a teljesítmény maximalizálása érdekében a fájlváltozásokat nem ellenőrzi a rendszer.

A konfigurációs fájlok betöltése a addConfig() segítségével történik:

$this->configurator->addConfig($this->rootDir . '/config/common.neon');

A addConfig() metódus többször is meghívható több fájl hozzáadásához.

$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');
}

A cli.php név nem elírás, a konfiguráció egy PHP fájlba is írható, amely tömbként adja vissza.

Alternatívaként használhatjuk a includes szekciót is, hogy több konfigurációs fájlt töltsünk be.

Ha a konfigurációs fájlokban azonos kulcsú elemek jelennek meg, akkor azok felülíródnak, vagy tömbök esetén összevonásra kerülnek. A később bevont fájlnak magasabb prioritása van, mint az előzőnek. Az a fájl, amelyben a includes szakasz szerepel, magasabb prioritással rendelkezik, mint a benne foglalt fájlok.

Statikus paraméterek

A konfigurációs fájlokban használt paramétereket a parameters szakaszban lehet definiálni, és a addStaticParameters() metódus (amelynek alias neve addParameters()) is átadhatja (vagy felülírhatja). Fontos, hogy a különböző paraméterértékek további DI-konténerek, azaz további osztályok generálását okozzák.

$this->configurator->addStaticParameters([
	'projectId' => 23,
]);

A konfigurációs fájlokban a %projectId% szokásos jelölést írhatjuk a projectId nevű paraméter eléréséhez.

Dinamikus paraméterek

A konténerhez dinamikus paramétereket is hozzáadhatunk, ezek eltérő értékei a statikus paraméterekkel ellentétben nem okoznak új DI-konténerek generálását.

$this->configurator->addDynamicParameters([
	'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);

A környezeti változókat könnyen elérhetővé tehetnénk dinamikus paraméterek segítségével. A konfigurációs fájlokban a %env.variable% címen keresztül érhetjük el őket.

$this->configurator->addDynamicParameters([
	'env' => getenv(),
]);

Alapértelmezett paraméterek

A konfigurációs fájlokban a következő statikus paramétereket használhatja:

  • %appDir% a Bootstrap.php fájl könyvtárának abszolút elérési útja.
  • %wwwDir% a index.php beviteli fájlt tartalmazó könyvtár abszolút elérési útja.
  • %tempDir% az ideiglenes fájlok könyvtárának abszolút elérési útja.
  • %vendorDir% az abszolút elérési út a könyvtárak Composer általi telepítésének könyvtárához.
  • %rootDir% a projekt gyökérkönyvtárának abszolút elérési útvonala.
  • %debugMode% jelzi, hogy az alkalmazás hibakeresési módban van-e.
  • %consoleMode% jelzi, hogy a kérés a parancssoron keresztül érkezett-e.

Importált szolgáltatások

Most mélyebbre megyünk. Bár a DI konténer célja az objektumok létrehozása, kivételesen szükség lehet arra, hogy egy meglévő objektumot beillesszünk a konténerbe. Ezt úgy tesszük meg, hogy a szolgáltatást a imported: true attribútummal definiáljuk.

services:
	myservice:
		type: App\Model\MyCustomService
		imported: true

Hozzunk létre egy új példányt, és illesszük be a bootstrapbe:

$this->configurator->addServices([
	'myservice' => new App\Model\MyCustomService('foobar'),
]);

Különböző környezetek

Ne habozzon, ha a Bootstrap osztályt saját igényei szerint alakíthatja. A bootWebApplication() metódushoz paramétereket adhat hozzá a webes projektek megkülönböztetése érdekében. Alternatívaként más metódusokat is hozzáadhat, például a bootTestEnvironment() a környezet inicializálásához a unit tesztekhez, a bootConsoleApplication() a parancssorból hívott szkriptekhez stb.

public function bootTestEnvironment(): Nette\DI\Container
{
	Tester\Environment::setup(); // Nette Tester inicializálása
	$this->setupContainer();
	return $this->configurator->createContainer();
}

public function bootConsoleApplication(): Nette\DI\Container
{
	$this->configurator->setDebugMode(false);
	$this->initializeEnvironment();
	$this->setupContainer();
	return $this->configurator->createContainer();
}
verzió: 4.0