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
{
	public static function boot(): Configurator
	{
		$appDir = dirname(__DIR__);
		$configurator = new Configurator;
		//$configurator->setDebugMode('secret@23.75.345.200');
		$configurator->enableTracy($appDir . '/log');
		$configurator->setTempDirectory($appDir . '/temp');
		$configurator->createRobotLoader()
			->addDirectory(__DIR__)
			->register();
		$configurator->addConfig($appDir . '/config/common.neon');
		return $configurator;
	}
}

index.php

A webes alkalmazások esetében a kezdő fájl a index.php, amely a www/ nyilvános könyvtárban található. Ez lehetővé teszi a Bootstrap osztály számára, hogy inicializálja a környezetet, és visszaadja a $configurator, amely létrehozza a DI konténert. Ezután megszerzi a Application szolgáltatást, amely a webalkalmazást futtatja:

// a környezet inicializálása + konfigurátor objektum kinyerése
$configurator = App\Bootstrap::boot();
// DI konténer létrehozása
$container = $configurator->createContainer();
// A DI konténer létrehoz egy Nette\Application\Application objektumot.
$application = $container->getByType(Nette\Application\Application::class);
// Nette alkalmazás indítása
$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 két alapvető módot különböztet meg, amelyben egy kérés végrehajtásra kerül: fejlesztési és termelési mód. A fejlesztési mód a programozó maximális kényelmére összpontosít, a Tracy megjelenik, a gyorsítótár automatikusan frissül, ha a sablonok vagy a DI konténer konfigurációja változik, stb. A termelési mód a teljesítményre összpontosít, a Tracy csak a hibákat naplózza, a sablonok és egyéb fájlok módosításait nem ellenőrzi.

A mód kiválasztása automatikus felismeréssel történik, így általában nem szükséges kézzel konfigurálni vagy váltani semmit. A mód fejlesztési, ha az alkalmazás localhoston fut (azaz a 127.0.0.1 vagy a ::1 IP-címen ) és nincs proxy (azaz a HTTP fejléce). Ellenkező esetben termelési üzemmódban fut.

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:

$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.

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

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

$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:

$configurator->enableTracy($appDir . '/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:

$configurator->setTempDirectory($appDir . '/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:

$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.

$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:

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

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

$configurator->addConfig($appDir . '/config/common.neon');
$configurator->addConfig($appDir . '/config/services.neon');
if (PHP_SAPI === 'cli') {
	$configurator->addConfig($appDir . '/config/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.

$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.

$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.

$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.
  • %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:

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

Különböző környezetek

Nyugodtan testre szabhatja a Bootstrap osztályt, hogy megfeleljen az igényeinek. A boot() metódushoz paramétereket adhat a webes projektek megkülönböztetéséhez, vagy más metódusokat is hozzáadhat, például a bootForTests(), amely inicializálja a környezetet a unit tesztekhez, a bootForCli() a parancssorból hívott szkriptekhez, és így tovább.

public static function bootForTests(): Configurator
{
	$configurator = self::boot();
	Tester\Environment::setup(); // Nette Tester inicializálása
	return $configurator;
}
verzió: 4.0