Bootstrap
Bootstrap je zaváděcí kód, který inicializuje prostředí, vytvoří dependency injection (DI) kontejner a spustí aplikaci. Řekneme si:
- jak se konfiguruje pomocí NEON souborů
- jak rozlišit produkční a vývojářský režim
- jak vytvořit DI kontejner
Aplikace, ať už jde o ty webové nebo skripty spouštěné z příkazové řádky, začínají svůj běh nějakou formou
inicializace prostředí. V dávných dobách to míval na starosti soubor s názvem třeba include.inc.php
, který
prvotní soubor inkludoval. V moderních Nette aplikacích jej nahradil soubor bootstrap.php
, který jakožto
součást aplikace najdete v souboru app/bootstrap.php
. Může vypadat kupříkladu takto:
$configurator = new Nette\Configurator;
//$configurator->setDebugMode('secret@23.75.345.200');
$configurator->enableTracy(__DIR__ . '/../log');
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
$configurator->addConfig(__DIR__ . '/config/config.neon');
// vytvoření DI kontejneru
$container = $configurator->createContainer();
index.php
Prvotní soubor je v případě webových aplikací index.php
, který se nachází ve veřejném adresáři
www/
. Ten si nechá od souboru bootstrap.php
inicializovat prostředí a vrátit DI kontejner
$container
. Z něj získá službu Application
, kterou spustí webovou aplikaci:
// inicializace prostředí + získání DI kontejneru
$container = require __DIR__ . '/../app/bootstrap.php';
// DI kontejner vytvoří objekt Nette\Application\Application
$application = $container->getByType(Nette\Application\Application::class);
// spuštění Nette aplikace
$application->run();
Jak vidno, s nastavením prostředí a vytvořením dependency injection (DI) kontejneru pomáhá třída Nette\Configurator, kterou si nyní blíže představíme.
Vývojářský vs produkční režim
Nette rozlišuje dva základní režimy, ve kterých se požadavek vykoná: vývojářský a produkční. Vývojářský je zaměřen na maximální pohodlí programátora, zobrazuje se Tracy, automaticky se aktualizuje cache při změně šablon nebo konfigurace DI kontejneru, atd. Produkční je zaměřený na výkon a ostré nasazení, Tracy chyby pouze loguje a změny šablon a dalších souborů se netestují.
Volba režimu se provádí autodetekcí, takže obvykle není potřeba nic konfigurovat nebo ručně přepínat. Režim je
vývojářský tehdy, pokud je aplikace spuštěna na localhostu (tj. IP adresa 127.0.0.1
nebo ::1
) a
není přitomna proxy (tj. její HTTP hlavička). Jinak běží v produkčním režimu.
Pokud chceme vývojářský režim povolit i v dalších případech, například programátorům přistupujícím
z konkrétní IP adresy, použijeme setDebugMode()
:
$configurator->setDebugMode('23.75.345.200'); // lze uvést i pole IP adres
Rozhodně doporučujeme kombinovat IP adresu s cookie. Do cookie nette-debug
uložíme tajný token, např.
secret1234
, a tímto způsobem aktivujeme vývojářský režim pro programátory přistupující z konkrétní IP
adresy a zároveň mající v cookie zmíněný token:
$configurator->setDebugMode('secret1234@23.75.345.200');
Vývojářský režim můžeme také vypnout úplně, i pro localhost:
$configurator->setDebugMode(false);
Debugovací nástroj Tracy
Pro snadné debugování ještě zapneme skvělý nástroj Tracy. Ve vývojářském režimu chyby vizualizuje a v produkčním režimu chyby loguje do uvedeného adresáře:
$configurator->enableTracy(__DIR__ . '/../log');
Dočasné soubory
Nette využívá cache pro DI kontejner, RobotLoader, šablony atd. Proto je nutné nastavit cestu k adresáři, kam se bude cache ukládat:
$configurator->setTempDirectory(__DIR__ . '/../temp');
Na Linuxu nebo macOS nastavte adresářům log/
a temp/
práva pro zápis.
RobotLoader
Zpravidla budeme chtít automaticky načítat třídy pomocí RobotLoaderu, musíme ho tedy nastartovat a necháme jej načítat třídy
z adresáře, kde je umístěný bootstrap.php
(tj. __DIR__
), a všech podadresářů:
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
Alternativní přístup je nechat třídy načítat pouze přes Composer při dodržení PSR-4.
Timezone
Přes konfigurátor můžete nastavit výchozí časovou zónu.
$configurator->setTimeZone('Europe/Prague');
Konfigurace DI kontejneru
Součástí bootovacího procesu je vytvoření DI kontejneru neboli továrny na objekty, což je srdce celé aplikace. Jde vlastně o PHP třídu, kterou vygeneruje Nette a uloží do adresáře s cache. Továrna vyrábí klíčové objekty aplikace a pomocí konfiguračních souborů jí instruujeme, jak je má vytvářet a nastavovat, čímž ovlivňujeme chování celé aplikace.
Konfigurační soubory se obvykle zapisují ve formátu NEON. V samostatné kapitole se dočtete, co vše lze konfigurovat.
Ve vývojářském režimu se kontejner automaticky aktualizuje při každé změně kódu nebo konfiguračních souborů. V produkčním režimu se vygeneruje jen jednou a změny se kvůli maximalizaci výkonu nekontrolují.
Konfigurační soubory načteme pomocí addConfig()
:
$configurator->addConfig(__DIR__ . '/config/config.neon');
Pokud chceme přidat více konfiguračních souborů, můžeme funkci addConfig()
zavolat vícekrát.
$configurator->addConfig(__DIR__ . '/config/config.neon');
$configurator->addConfig(__DIR__ . '/config/config.local.neon');
if (PHP_SAPI === 'cli') {
$configurator->addConfig(__DIR__ . '/config/cli.php');
}
Název cli.php
není překlep, konfigurace může být zapsaná také v PHP souboru, který ji vrátí
jako pole.
Také můžeme přidat další konfigurační soubory v sekci includes
.
Pokud se v konfiguračních souborech objeví prvky se stejnými klíči, budou přepsány, nebo v případě polí sloučeny. Později vkládaný
soubor má vyšší prioritu než předchozí. Soubor, ve kterém je sekce includes
uvedena, má vyšší prioritu
než v něm inkludované soubory.
Statické parametry
Parametry používané v konfiguračních souborech můžeme definovat v sekci parameters
a také
je předávat (či přepisovat) metodou addParameters()
. Důležité je, že různé hodnoty parametrů způsobí
vygenerování dalších DI kontejnerů, tedy dalších tříd.
$configurator->addParameters([
'projectId' => 23,
]);
Na parametr projectId
se lze v konfiguraci odkázat obvyklým zápisem %projectId%
. Třída
Configurator automaticky přidává parametry appDir
, wwwDir
, tempDir
,
debugMode
a consoleMode
.
Dynamické parametry
Do kontejneru můžeme přidat i dynamické parametry, jejichž různé hodnoty na rozdíl od statických parameterů nezpůsobí generování nových DI kontejnerů.
$configurator->addDynamicParameters([
'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);
Jednoduše tak můžeme přidat např. environmentální proměnné, na které se pak lze v konfiguraci odkázat zápisem
%env.variable%
.
$configurator->addDynamicParameters([
'env' => $_ENV,
]);
Importované služby
Nyní už jdeme hlouběji. Ačkoliv je smyslem DI kontejneru objekty vyrábet, výjimečně může vzniknout potřeba do
kontejneru existující objekt vložit. Uděláme to tak, že službu definujeme s příznakem dynamic: true
.
services:
myservice:
class: App\Model\MyCustomService
dynamic: true
A v bootstrapu do kontejneru vložíme objekt:
$configurator->addServices([
'myservice' => new App\Model\MyCustomService('foobar'),
]);