You are browsing the unmaintained documentation for old Nette 2.1. See documentation for current Nette.

Konfigurace

Systémový kontejner je DI kontejner, ve kterém se nacházejí všechny služby a parametry potřebné pro běh aplikace. Řekneme si:

  • jak systémový kontejner vytvořit
  • jak se konfiguruje pomocí NEON souborů
  • jak na produkční a vývojářský režim
  • jak používat a vytvářet rozšíření pro kontejner

Omlouváme se, tato stránka je ještě v přípravě.

Systémový kontejner je statický Dependency Injection kontejner, ve kterém se nacházejí všechny služby a parametry potřebné pro běh aplikace. Tedy nejen služby frameworku samotného, ale i všech knihoven, které se rozhodnete použít. Jak takový základní kontejner vypadá, se můžete podívat třeba tady.

V praxi se ukázalo, že programování kontejnerů je značně rutinní a nezáživná činnost. Navíc s tím, jak aplikace roste, je stále těžší se v něm orientovat. Pohodlným řešením je nechat si kontejner vygenerovat. Což Nette Framework umí. Stručným konfiguračním jazykem popíšeme, jaké služby má obsahovat a framework sám PHP kód vytvoří. S pravdou ven: i kód výše odkazovaného kontejneru byl vygenerován.

Configurator

Generování kontejneru je úkolem třídy Nette\Configurator. Samotný PHP kód se vytváří jen jednou a poté uloží do cache, proto musíme určit složku pro dočasné soubory:

$configurator = new Nette\Configurator;
$configurator->setTempDirectory(__DIR__ . '/../temp');

Poté stačí uvést cestu ke konfiguračnímu souboru:

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

A vytvoření instance je už maličkost:

// vrací objekt třídy SystemContainer
$container = $configurator->createContainer();

Prostředí

Configurator se pokouší detekovat, zda aplikace běží na ostrém (production) nebo vývojářském (development) serveru. Činí tak podle IP adresy počítače, z něhož k serveru přistupujete. Pokud je 127.0.0.1, považuje server za vývojářský. Zjistit prostředí nemůžete, ale to nevadí, protože se používá pouze pro volbu sekce při načítání konfigurace a to můžete ovlivnit parametrem při volání addConfig().

$environment = Nette\Configurator::detectDebugMode('vaše ip adresa')
    ? $configurator::DEVELOPMENT
    : $configurator::PRODUCTION;

$configurator->addConfig(__DIR__ . '/config/config.neon', $environment);

Jako $environment můžete předat jakýkoliv řetězec, nejen production či development. Můžete si tímto způsobem vyžádat použití libovolné sekce ve vašem konfiguračním souboru. Detekci takového prostředí však musíte řešit sami, ať už pomocí systémové proměnné (třeba getenv("COMPUTERNAME")) nebo doménového jména serveru ($_SERVER['SERVER_NAME']).

Vývojářský režim

Trochu jiná věc je režim, v jakém k aplikaci přistupujete. Pro aktivaci laděnky můžete chtít přistupovat k produkčnímu serveru jako vývojář. Rozpoznává se podle stejného principu. Režim zjistíte metodou isDebugMode() a nastavíte pomocí setDebugMode(). Hodí se především, pokud aktivujete debugger pomocí enableDebugger(), která musí následovat až po nastavení režimu.

// aktivuje laděnku pouze pro dané ip adresy
$configurator->setDebugMode(array('90.180.45.360', '90.180.45.361'));
// nebo všem
$configurator->setDebugMode(); // = TRUE
// nebo nikomu
$configurator->setDebugMode($configurator::NONE); // = FALSE

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

RobotLoader

Pro sestavení kontejneru je potřeba načíst všechny třídy, které se v konfiguračním souboru uvádějí. K tomu je obvykle třeba aktivovat auto-loading. Třída Configurator nám vychází vstříc metodou, která vyrobí RobotLoader, nám pak stačí uvést indexované adresáře a robota aktivovat. Nezapomeňte tak učinit ještě před samotným voláním createContainer().

$configurator->createRobotLoader()
    ->addDirectory(__DIR__)
    ->addDirectory(__DIR__ . '/../lib')
    ->register();

Konfigurace frameworku

Konfigurace se obykle zapisuje v NEON souboru. Se syntaxí si můžete pohrát na stránce http://ne-on.org.

Většinu parametrů Nette Frameworku lze nyní ovlivnit pomocí konfiguračního souboru. Nette Framework sám sebe konfiguruje pomocí rozšíření DI Containeru, které přijímá parametry v sekci nette v konfiguračním souboru, která se nachází pod hlavní sekcí common (pokud ji používáte).

Sessions

Lze nastavovat všechny PHP direktivy (ve formátu camelCase).

nette:
    session:
        autoStart: true  # výchozí je smart
        expiration: 10 days
        name: ...
        ...

Doporučuje se používat autoStart: smart, protože pak automaticky startuje session, pouze pokud je již vytvořena.

Více o konfiguraci sessions.

Application

nette:
    application:
        debugger: true # panel do Laděnky
        catchExceptions: ...
        errorPresenter: ...

Routování

nette:
    routing:
        debugger: true  # panel v Debugger baru
        routes:
                index.php: Dashboard:default
                '<presenter>/<action>[/<id>]': Dashboard:default

Konfigurace rout je zatím experimentální.

Security

Uvedením pole users vytvoříme SimpleAuthenticator, uvedením polí roles nebo resources vytvoříme autorizátor Nette\Security\Permission.

nette:
    security:
        debugger: true  # panel v Debugger baru
        frames: ... # ovlivňuje hlavičku X-Frame-Options

        users:
            frantisek: tajneheslo

        roles:
            guest:
            member:
            admin: [member]  # admin dědí od membera

        resources:
            file:

Framework z bezpečnostních důvodů odesílá hlavičku X-Frame-Options: SAMEORIGIN, která říká, že stránku lze zobrazit uvnitř jiné stránky (v elementu IFRAME) pouze pokud se nachází na stejné doméně. To může být v některých situacích nežádoucí (například pokud vyvíjíte aplikaci pro Facebook), chování lze proto vypnout nastavením položky frames: yes.

Maily

Standardní mailer je SendmailMailer, uvedením smtp aktivujeme SmtpMailer.

nette:
    mailer:
        smtp: true # zapne SmtpMailer místo SendmailMailer
        # dále lze uvést host, port, username, password, secure, timeout

Databáze

Můžeme vytvořit více připojení, které uvedeme pod klíčem database. Takto vytvoříme spojení nazvané default.

nette:
    database:
        default:
            dsn: "sqlite2:%appDir%/models/demo.db"
            user: ...
            password: ...
            options: [PDO::MYSQL_ATTR_COMPRESS = true]
            debugger: false # panel v Debugger baru
            explain: false  # explain dotazů v Debugger baru
            reflection: discovered # nebo conventional nebo název třídy

Framework tak vytvoří nejen objekt Nette\Database\Connection, ale nastavují mu i pomocné objekty jako reflection & cache a ve vývojářském režimu přidá panel do Debugger baru.

V rámci konfiguračního souboru se můžeme ke službě dostat přes autowiring (@Nette\Database\Connection), přes název služby (@nette.database.default) nebo si vytvořit alias a ten používat:

services:
    database: @nette.database.default

    authorizator: Auth(@database)

Formuláře

V konfiguračním souboru lze změnit výchozí chybové hlášky.

nette:
    forms:
        messages:
            EQUAL: 'Please enter %s.'
            FILLED: 'Please complete mandatory field.'
            MIN_LENGTH: 'Please enter a value of at least %d characters.'
            EMAIL: '%label must be valid e-mail'

Šablony

Lze přepínat HTML a XHTML režim šablon:

nette:
    xhtml: no  # výchozí je false

DI

nette:
    container:
        debugger: true  # aktivuje panel v Debugger baru

Debugger

Lze konfigurovat některé parametry Nette\Diagnostics\Debugger a nastavovat panely do Debugger baru.

nette:
    debugger:
        email: %webmasterEmail%
        strictMode: TRUE
        editor: ...
        browser: ...
        bar: # panely do Debugger baru
            - Nette\DI\Diagnostics\ContainerPanel # alias DI Container baru
            - IncludePanel
            - XDebugHelper('myIdeKey')
            - MyPanel(@MyService)
        blueScreen: # panely do Laděnky
            - DoctrinePanel::renderException

Low-level úpravy

Všechna tato nastavení ovlivňují podobu výsledného systémového DI kontejneru. Oproti přímému zápisu do sekcí services či factories nabízejí srozumitelnější a stručnější syntax. Nicméně zůstává možnost si jednotlivé služby ještě „doladit“ na nižší úrovni:

services:
    nette.mailer:
        class: MySmtpMailer

    nette.presenterFactory:
        class: MyPresenterFactory

Nebo vytvořit nové služby poděděním existujících:

services:
    myPresenterFactory < nette.presenterFactory
        setup:
            - setMapping([])

Vlastní služby

Konfigurační soubor je místem, kam umísťujeme definice vlastních služeb. Slouží k tomu sekce services. Například tato definice služby:

services:
    database: Nette\Database\Connection(%dsn%, %user%, %password%)

# nebo ve dvou řádcích:
    database:
        factory: Nette\Database\Connection(%dsn%, %user%, %password%)

# nebo ve třech řádcích :-)
    database:
        class: Nette\Database\Connection
        arguments: [%dsn%, %user%, %password%]

Vygeneruje:

function createServiceDatabase()
{
    return new Nette\Database\Connection(
        $this->parameters['dsn'],
        $this->parameters['user'],
        $this->parameters['password']
    );
}

Definice služby:

services:
    database:
        class: Nette\Database\Connection
        factory: DbFactory::createConnection

DbFactory::createConnection:

class DbFactory
{
    static function createConnection(Nette\DI\Container $container)
    {
        ...
    }
}

Vygeneruje:

function createServiceDatabase()
{
    return DbFactory::createConnection($this);
}

Setup

services:
    database:
        factory: Nette\Database\Connection(%dsn%, %user%, %password%)
        setup:
            - setCacheStorage(@cacheStorage)

Vygeneruje:

function createServiceDatabase()
{
    $service = new Nette\Database\Connection(...);
    $service->setCacheStorage($this->cacheStorage);
    return $service;
}

Autowiring umí odkazy na jiné služby doplnit automaticky, takže lze parametry úplně vynechat:

setup:
    - setCacheStorage

Pokud služba cacheStorage neexistuje, můžeme jako parametr uvést výsledek volání funkce:

setup:
    - setCacheStorage( Factory::createStorage() )

# nebo metody jiné služby:
    - setCacheStorage( @factory::createStorage() )

Případně nově vytvořenou třídu:

setup:
    - setCacheStorage( Nette\Caching\Storages\FileStorage(%tempDir%) )

# vygeneruje: $service->setCacheStorage(new Nette\Caching\Storages\FileStorage(...));

Lze nastavovat i hodnoty proměnných:

substitutions

setup:
    - $substitutions( [db: test] )

# vygeneruje: $service->substitutions = array('db' => 'test');

Kompletní příklad:

parameters:
    database:
        driver: mysql
        host: localhost
        dbname: test
        user: jim
        password: beam
        substitutions:
            db: test

services:
    database:
        factory: Nette\Database\Connection(
            '%database.driver%:host=%database.host%;dbname=%database.dbname%',
            %database.user%, %database.password%, null,
            Nette\Database\Reflection\DiscoveredReflection()
        )
        setup:
            - setCacheStorage
            - $substitutions( %database.substitutions% )

Anonymní služby

V konfiguračním souboru mohou být i služby, na které již není odkazováno v žádném dalším konfiguračním souboru. Takové služby není potřeba pojmenovávat. Pro anonymní služby použijte následující syntax:

services:
    - Simple\Service

    -
        factory: Complex\Service
        setup:
            - setLang(%lang%)

Pokud však budete chtít později odkázat na anonymní službu, budete muset uvést úplný název třídy (rozhraní).

services:
    router: @App\RouterFactory::createRouter

Také je potřeba mít na paměti, že z povahy anonymních služeb nelze mít registrovaných více instancí stejného typu, jelikož by nebylo možné je rozlišit.

Dědičnost služeb

services:
    dev_database < database
        setup:
            - Diagnostics\ConnectionPanel::initialize

Auto-wiring

Auto-wiring umí automaticky předávat do konstruktoru a dalších metod požadované služby. Řídí se podle type hintů a anotací @return. Služba odpovídající hledané třídě musí být v kontejneru právě jedna, jinak se vyhodí výjimka.

Pokud potřebujeme definovat více služeb stejného typu, můžeme je z auto-wiringu vyřadit:

services:
    cacheStorage:
        factory: Nette\Caching\Storages\FileStorage(%tempDir%)

    tempCacheStorage:
        factory: Nette\Caching\Storages\DevNullStorage
        autowired: no

Pokud upravujeme základní služby Nette Frameworku, nesmíme se zapomenout ujistit, že kontejner zná třídy naší implementace. Pokud tedy nastavujeme vlastní factory pro službu, tak to znamená mít správně absolutní název třídy v annotaci @return, nebo nastavovat vždy i třídu do class.

Více konfiguračních souborů

Vkládané soubory se uvádějí v sekci includes.

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

Konfigurace se slučují tak, že nejvyšší prioritu má soubor obsahující sekci includes a nejnižší první vkládaný soubor. Slučování polí lze zabránit uvedením vykřičníku za název pole:

argument!: [1, 2, 3]