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
{
$rootDir = dirname(__DIR__);
$configurator = new Configurator;
//$configurator->setDebugMode('secret@23.75.345.200');
$configurator->enableTracy($rootDir . '/log');
$configurator->setTempDirectory($rootDir . '/temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
$configurator->addConfig($rootDir . '/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($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:
$configurator->setTempDirectory($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:
$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($rootDir . '/config/common.neon');
A addConfig()
metódus többször is meghívható több fájl hozzáadásához.
$configurator->addConfig($rootDir . '/config/common.neon');
$configurator->addConfig($rootDir . '/config/services.neon');
if (PHP_SAPI === 'cli') {
$configurator->addConfig($rootDir . '/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%
aBootstrap.php
fájl könyvtárának abszolút elérési útja.%wwwDir%
aindex.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:
$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;
}