Bootstrap

Bootstrap je zaváděcí soubor, který inicializuje prostředí a vytvoří Dependency Injection (DI) kontejner. Řekneme si:

  • jak se konfiguruje pomocí NEON souborů
  • jak na produkční a vývojářský režim
  • jak vytvořit DI kontejner

Nastavení prostředí a vytvoření Dependency Injection (DI) kontejneru má v Nette na starosti třída Configurator. Používá se v zaváděcím souboru bootstrap.php umístěném ve složce app/.

Vývojářský režim

Vývojářský režim je automaticky aktivní, pokud vyvíjíme na localhostu. Chceme-li ho povolit i mimo něj, 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

Ještě bezpečnější je kombinace IP adresy a 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é zcela vypnout:

$configurator->setDebugMode(false);

Debugovací nástroj Tracy

Pro snadné debugování ještě zapneme Tracy a chyby necháme logovat do uvedeného adresáře:

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

Cachování konfigurace

Konfigurace se načte a zpracuje jen jednou a výsledek se uloží do cache, což zásadním způsobem aplikaci zrychluje. Proto nastavíme cestu setTempDirectory(), kam se bude cache ukládat.

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

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, a všech podadresářů (tj. __DIR__):

$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 defaultní hodnotu timezone.

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

Konfigurační soubory

Podle konfiguračních souborů se generuje systémový DI kontejner, který je srdcem celé aplikace. Obvykle se zapisují ve formátu NEON. V samostatné kapitole se dočtete, co vše lze konfigurovat.

Konfigurační soubory vložíme 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/common.neon');
$configurator->addConfig(__DIR__ . '/config/local.neon');
if (PHP_SAPI === 'cli') {
    $configurator->addConfig(__DIR__ . '/config/cli.neon');
}

Alternativně můžeme přidat více konfiguračních souborů jejich uvedením v sekci includes:

includes:
    - parameters.php
    - services.neon
    - presenters.neon

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 se sekcí includes má vyšší prioritu než v něm uvedené soubory.

Parametry

Parametry do DI kontejneru můžeme předat metodou addParameters(). Hodnoty těchto parametrů musí být známe v době kompilace. Proto se pro různé hodnoty vygenerují různé kontejnery.

$configurator->addParameters([
    'foo' => 'bar',
    'baz' => '%tempDir%',
]);

Na parameter foo se lze v konfiguraci odkázat zápisem %foo%. Konfigurátor automaticky přidává parametry appDir, wwwDir, tempDir, debugMode a consoleMode.

Dynamické parametry

Do kontejneru můžeme přidat i dynamické parametry, jejichž hodnota může být při každém požadavku jiná. Tím pádem nezpůsobí přegenerování kontejneru.

$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,
]);

Dynamické služby

Do DI kontejneru můžeme vložit vlastní instanci třídy, namísto toho, aby ji vytvářel sám. Službu musíme definovat 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'),
]);

Vytvoření kontejneru

Třídu kontejneru vygeneruje a jeho instanci vrátí createContainer():

/** @var Nette\DI\Container $container */
$container = $configurator->createContainer();

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 v souborech se kvůli výkonu nekontrolují.

index.php

Pokud vytváříme webovou aplikaci, všechny požadavky jdou přes jediný PHP soubor, který se nachází ve veřejném adresáři www/, a tím je soubor index.php. Ten předává řízení do aplikace (tj. do adresáře app/) zaváděcímu souboru bootstrap.php. Následně index.php získá z kontejneru DI službu, kterou spustí webovou aplikaci:

$container = require __DIR__ . '/../app/bootstrap.php';
$container->getByType(Nette\Application\Application::class)
    ->run();