Nette Documentation Preview

syntax
Bootstrap
*********

<div class=perex>

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

</div>


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:

```php
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 .[#toc-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:

```php
// 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 [api: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 .[#toc-development-vs-production-mode]
=======================================================================

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:

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

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

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

```php
$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 .[#toc-debugging-tool-tracy]
====================================================

Az egyszerű hibakeresés érdekében bekapcsoljuk a [Tracy |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:

```php
$configurator->enableTracy($appDir . '/log');
```


Ideiglenes fájlok .[#toc-temporary-files]
=========================================

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:

```php
$configurator->setTempDirectory($appDir . '/temp');
```

Linuxon vagy macOS-en állítsa be a `log/` és a `temp/` könyvtárak [írási engedélyeit |nette:troubleshooting#Setting directory permissions].


RobotLoader .[#toc-robotloader]
===============================

Általában a [RobotLoader |robot-loader:] 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:

```php
$configurator->createRobotLoader()
	->addDirectory(__DIR__)
	->register();
```

Egy alternatív megoldás az, hogy csak a [Composer |best-practices:composer] PSR-4 automatikus betöltését használjuk.


Időzóna .[#toc-timezone]
========================

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

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


DI konténer konfigurálása .[#toc-di-container-configuration]
============================================================

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 |neon:format] írjuk. Itt olvashatja el, hogy mit lehet [konfigurálni |nette:configuring].

.[tip]
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:

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

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

```php
$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 |dependency-injection:configuration#including files] 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 |dependency-injection:configuration#Merging] tömbök esetén [összevonásra |dependency-injection:configuration#Merging] 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 .[#toc-static-parameters]
----------------------------------------------

A konfigurációs fájlokban használt paramétereket a [`parameters` szakaszban |dependency-injection:configuration#parameters] 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.

```php
$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 .[#toc-dynamic-parameters]
------------------------------------------------

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.

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

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


Alapértelmezett paraméterek .[#toc-default-parameters]
------------------------------------------------------

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 .[#toc-imported-services]
--------------------------------------------------

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.

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

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

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


Különböző környezetek .[#toc-different-environments]
====================================================

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.

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

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.
  • %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;
}