Konfigurace

Přehled všech konfiguračních voleb v Nette Frameworku.

Různé součásti Nette nastavujeme pomocí konfiguračních souborů. Ty se obvykle zapisují ve formátu NEON, s jehož syntaxí se seznamte. K editaci doporučujeme editory s podporou tohoto formátu.

Chcete-li zapsat řetězec začínající znakem @ nebo obsahující %, musíte znak escapovat zdvojením na @@ nebo %%.

 application: 	Application
constants: Definice PHP konstant
database: Databáze
decorator: Dekorátor
di: DI kontejner
extensions: Instalace dalších DI rozšíření
forms: Formuláře
http: HTTP hlavičky
includes: Vkládání souborů
latte: Šablony Latte
mail: Maily
parameters: Parametry
php: PHP konfigurace
routing: Routování
security: Přístupová oprávnění
services: Služby
session: Session
tracy: Tracy debugger

Application

Základní nastavení chování Nette Application.

application:
	# zobrazit "Nette Application" panel v Tracy BlueScreen?
	debugger: ...           # (bool) výchozí je true

	# bude se při chybě volat error-presenter?
	catchExceptions: ...    # (bool) výchozí je true v produkčním režimu

	# název error-presenteru
	errorPresenter: Error   # (string) výchozí je 'Nette:Error'

	# chybné odkazy negenerují varování?
	# má efekt pouze ve vývojářském režimu
	silentLinks: ...        # (bool) výchozí je false

Protože ve vývojovém režimu se error-presentery standardně nevolají a chybu zobrazí až Tracy, změnou hodnoty catchExceptions na true můžeme při vývoji ověřit jejich správnou funkčnost.

Volba silentLinks určuje, jak se Nette zachová ve vývojářském režimu, když selže generování odkazu (třeba proto, že neexistuje presenter, atd). Výchozí hodnota false znamená, že Nette vyhodí E_USER_WARNING chybu. Nastavením na true dojde k potlačení této chybové hlášky. V produkčním prostředí se E_USER_WARNING vyvolá vždy. Toto chování můžeme také ovlivnit nastavením proměnné presenteru $invalidLinkMode.

Mapování

Definuje pravidla, podle kterých se z názvu presenteru (třeba Homepage) odvodí název třídy (třeba App\Presenters\HomepagePresenter). Právě takového mapování lze docílit následující konfigurací:

application:
	mapping:
		*: App\Presenters\*Presenter

Název presenteru se nahradí za hvezdičku a výsledkem je název třídy. Snadné!

Pokud presentery členíme do modulů, můžeme pro každý modul mít vlastní mapování:

application:
	mapping:
		Front: App\FrontModule\*Presenter
		Admin: App\AdminModule\*Presenter
		Error: App\Error\*Presenter

Nyní se presenter Front:Homepage mapuje na třídu App\FrontModule\HomepagePresenter a presenter Admin:Dashboard na třídu App\AdminModule\DashboardPresenter.

Šikovnější bude vytvořit obecné (hvězdičkové) pravidlo, které první dvě nahradí a přibude v něm hvezdička navíc právě pro modul:

application:
	mapping:
		*: App\*Module\*Presenter
		Error: App\ModuleError\*Presenter

Opět presenter Front:Homepage namapuje na třídu App\FrontModule\HomepagePresenter.

Ale co když používáme vícenásobně zanořené moduly a máme třeba presenter Admin:User:Edit? V takovém případě se segment s hvězdičkou představující modul pro každou úroveň jednoduše zopakuje a výsledkem bude třída App\AdminModule\UserModule\EditPresenter.

Alternativním zápisem je použít místo řetězce použít pole skládající se ze tří segmentů:

application:
	mapping:
		*: [App, *Module, *Presenter]

I v tomto případě bude výsledkem třída App\AdminModule\UserModule\EditPresenter.

Výchozí hodnotou je *: *Module\*Presenter.

Automatická registrace presenterů

Nette automaticky přidává presentery jako služby do DI kontejneru, což zásadně zrychlí jejich vytváření. Jak Nette presentery dohledává lze konfigurovat:

application:
	# hledat presentery v Composer class map?
	scanComposer: ...      # (bool) výchozí je true

	# jaký řetězec musí obsahovat název třídy a souboru?
	scanFilter: ...        # (string) výchozí je 'Presenter'

	# ve kterých adresářích hledat presentery?
	scanDirs:              # (string[]|false) výchozí je '%appDir%'
		- %vendorDir%/mymodule

Adresáře uvedené v scanDirs nepřepisují výchozí hodnotu %appDir%, ale doplňují ji, scanDirs tedy bude obsahovat obě cesty %appDir% a %vendorDir%/mymodule. Pokud bychom chtěli výchozí adresář vynechat, použijeme vykřičník, který hodnotu přepíše:

application:
	scanDirs!:
		- %vendorDir%/mymodule

Skenování adresářů lze vypnout uvedením hodnoty false. Nedoporučujeme úplně potlačit automatické přidávání presenterů, protože jinak dojde ke snížení výkonu aplikace.

Konstanty

Vytváření PHP konstant.

constants:
	FOOBAR: 'baz'

Po nastartování aplikace bude vytvořena konstanta FOOBAR.

Databáze

Konfigurace jednoho či více databázových spojení pro Nette Database.

database:
	# DSN, jediný povinný klíč
	dsn: "sqlite2:%appDir%/Model/demo.db"

	# uživatelské jméno
	user: ...

	# heslo
	password: ...

Vytvoří služby typu Nette\Database\Connection a také Nette\Database\Context pro vrstvu Database Explorer. Databáze se obvykle předává autowiringem, není-li to možné, použijte názvy služeb @database.default.connection resp. @database.default.context.

Další nastavení:

database:
	# zobrazit database panel v Tracy Bar?
	debugger: ...     # (bool) výchozí je true

	# zobrazit EXPLAIN dotazů v Tracy Bar?
	explain: ...      # (bool) výchozí je true

	# povolit autowiring pro toto spojení?
	autowired: ...    # (bool) výchozí je true u prvního připojení

	# konvence tabulek: discovered, static nebo jméno třídy
	conventions: discovered  # (string) výchozí je 'discovered'

	options:
		# připojovat se k databázi teprve když je potřeba?
		lazy: ...     # (bool) výchozí je false

		# PHP třída ovladače databáze
		driverClass:  # (string)

		# lze uvádět volby, které najdete v dokumentaci ovladačů PDO
		PDO::MYSQL_ATTR_COMPRESS: true

V konfiguraci můžeme definovat i více databázových spojení rozdělením do pojmenovaných sekcí:

database:
	main:
		dsn: 'mysql:host=127.0.0.1;dbname=test'
		user: root
		password: password

	another:
		dsn: 'sqlite2::memory:'

Každé takto definované spojení vytváří služby zahrnující v názvu i název sekce, tj. @database.main.connection & @database.main.context a dále @database.another.connection & @database.another.context.

Autowiring je zapnutý jen u služeb z první sekce. Lze to změnit pomocí autowired: false nebo autowired: true. Neautowirované služby předáváme explicitně:

services:
	- UserManager(@database.another.connection)

Decorator

Jak upravit hromadně všechny služby určitého typu? Třeba zavolat určitou metodu u všech presenterů, které dědí od konkrétního společného předka? Od toho je tu decorator.

decorator:
	# u všech služeb, co jsou instancí této třídy nebo rozhraní
	App\Presenters\BasePresenter:
		setup:
			- setProjectId(10)       # zavolej tuto metodu
			- $absoluteUrls = true   # a nastav proměnnou

Decorator se dá používat také pro nastavení tagů nebo zapnutí režimu inject.

decorator:
	InjectableInterface:
		tags: [mytag: 1]
		inject: true

DI

Technické nastavení DI kontejneru.

di:
	# zobrazit DIC v Tracy Bar?
	debugger: ...        # (bool) výchozí je true

	# typy parametrů, které nikdy neautowirovat
	excluded: ...        # (string[])

	# třída, od které dědí DI kontejner
	parentClass: ...     # (string) výchozí je Nette\DI\Container

Rozšíření

Registrace dalších DI rozšíření. Tímto způsobem přidáme např. DI rozšíření Dibi\Bridges\Nette\DibiExtension22 pod názvem dibi

extensions:
	dibi: Dibi\Bridges\Nette\DibiExtension22

Následně ho tedy konfigurujeme v sekci dibi:

dibi:
	host: localhost

Jako rozšíření lze přidat i třídu, která má parametry:

extensions:
	application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, %appDir%, %tempDir%/cache)

Formuláře

V konfiguraci lze změnit výchozí chybové hlášky formulářů.

forms:
	messages:
		EQUAL: 'Zadejte %s.'
		NOT_EQUAL: 'Tato hodnota by neměla být %s.'
		FILLED: 'Toto pole je povinné.'
		BLANK: 'Toto pole by mělo být prázdné.'
		MIN_LENGTH: 'Zadejte prosím alespoň %d znaků.'
		MAX_LENGTH: 'Zadejte prosím maximálně %d znaků.'
		LENGTH: 'Zadejte prosím hodnotu %d až %d znaků dlouho.'
		EMAIL: 'Zadejte platnou e-mailovou adresu.'
		URL: 'Zadejte prosím platné URL.'
		INTEGER: 'Zadejte platné celé číslo.'
		FLOAT: 'Zadejte platné číslo.'
		MIN: 'Zadejte prosím hodnotu větší nebo rovnou %d.'
		MAX: 'Zadejte prosím hodnotu menší nebo rovnou %d.'
		RANGE: 'Zadejte hodnotu mezi %d a %d.'
		MAX_FILE_SIZE: 'Velikost nahraného souboru může být nejvýše %d bytů.'
		MAX_POST_SIZE: 'Nahraná data překračují limit %d bytů.'
		MIME_TYPE: 'Nahraný soubor není v očekávaném formátu.'
		IMAGE: 'Nahraný soubor musí být obraz ve formátu JPEG, GIF, PNG nebo WebP.'
		Nette\Forms\Controls\SelectBox::VALID: 'Vyberte prosím platnou možnost.'
		Nette\Forms\Controls\UploadControl::VALID: 'Při nahrávání souboru došlo k chybě.'
		Nette\Forms\Controls\CsrfProtection::PROTECTION: 'Vaše relace vypršela. Vraťte se na domovskou stránku a zkuste to znovu.'

HTTP hlavičky

http:
	# hlavičky, které se s každým požadavkem odešlou
	headers:
		X-Powered-By: MyCMS
		X-Content-Type-Options: nosniff
		X-XSS-Protection: '1; mode=block'

	# ovlivňuje hlavičku X-Frame-Options
	frames: ...      # (string|bool) výchozí je 'SAMEORIGIN'

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 změnit nastavením frames: http://allowed-host.com nebo frames: true.

Snadno lze sestavovat hlavičky Content-Security-Policy (dále CSP), jejich popis najdete v popisu CSP. CSP direktivy (jako např. script-src) mohou být zapsány buď jako řetězce dle specifikace, nebo jako pole hodnot kvůli lepší čitelnosti. Pak není potřeba kolem klíčových slov, jako třeba 'self', psát uvozovky. Nette také automaticky vygeneruje hodnotu nonce, takže v hlavičce bude třeba 'nonce-y4PopTLM=='.

http:
	# Content Security Policy (od nette/http 2.4.10)
	csp:
		# řetězec ve tvaru dle specifikace CSP
		default-src: "'self' https://example.com"

		# pole hodnot
		script-src:
			- nonce
			- strict-dynamic
			- self
			- https://example.com

		# bool v případě přepínačů
		upgrade-insecure-requests: true
		block-all-mixed-content: false

V šablonách používejte <script n:nonce>...</script> a hodnota nonce se doplní automaticky. Dělat bezpečné weby v Nette je opravdu snadné.

Podobně lze sestavit i hlavičky Content-Security-Policy-Report-Only (které lze používat souběžně s CSP) a Feature Policy:

http:
	# Content Security Policy Report-Only
	cspReportOnly:
		default-src: self
		report-uri: 'https://my-report-uri-endpoint'

	# Feature Policy
	featurePolicy:
		unsized-media: none
		geolocation:
			- self
			- https://example.com

Lze změnit vychozí chování parametru $secure u metody Nette\Http\Response::setCookie().

http:
	# posílat cookie pouze přes HTTPS?
	cookieSecure: ...      # (bool|auto) výchozí je false

Auto znamená, že pokud web běží na HTTPS, budou se cookies odesílat se $secure = true.

HTTP proxy

Pokud web běží za HTTP proxy, zadejte její IP adresu, aby správně fungovala detekce IP adresy klienta Nette\Http\Response::getRemoteAddress() a spojení přes HTTPS isSecured().

http:
	# IP adresa, rozsah (např. 127.0.0.1/8) nebo pole těchto hodnot
	proxy: 127.0.0.1       # (string|string[]) výchozí je nenastaveno

Vkládání souborů

Další konfigurační soubory můžeme vložit v sekci includes:

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

Název parameters.php není překlep, konfigurace může být zapsaná také v PHP souboru, který ji vrátí jako pole:

<?php
return [
	'database' => [
		'main' => [
			'dsn' => 'sqlite::memory:',
		],
	],
];

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 vkládané soubory.

Šablony Latte

Tímto nastavením lze globálně ovlivnit chování Latte v komponentách a presenterech.

latte:
	# přepne Latte do XHTML režimu
	xhtml: ...           # (bool) výchozí je false

	# třída objektu $this->template
	templateClass: App\MyTemplateClass # výchozí je Nette\Bridges\ApplicationLatte\Template

Dále lze registrovat nové tagy (makra) a to buď uvedením jména třídy, nebo referencí na službu. Jako výchozí je zavolána metoda install(), ale to lze změnit tím, že uvedeme jméno jiné metody:

latte:
	# registrace uživatelských Latte značek
	macros:
		- App\MyLatteMacros::register         # statická metoda, classname nebo callable
		- @App\MyLatteMacrosFactory           # služba s metodou install()
		- @App\MyLatteMacrosFactory::register # služba s metodou register()

services:
	- App\MyLatteMacrosFactory

Maily

Pro odesílání e-mailů se standardně používá mailer Nette\Mail\SendmailMailer, který se dále nekonfiguruje. Můžeme jej však přepnout na Nette\Mail\SmtpMailer:

mail:
	# použije SmtpMailer
	smtp: true       # (bool) výchozí je false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	secure: ...      # (ssl|tls|null) výchozí je null
	clientHost: ...  # (string) výchozí je $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) výchozí je false

Parametry

V konfiguraci můžete definovat parametry, které lze pak použít jako součást definic služeb. Čímž můžete zpřehlednit konfiguraci nebo sjednotit a vyčlenit hodnoty, které se budou měnit.

parameters:
	dsn: 'mysql:host=127.0.0.1;dbname=test'
	user: root
	password: secret

Na parametr dsn se odkážeme kdekoliv v konfiguraci zápisem %dsn%. Parametry lze používat i uvnitř řetězců jako '%wwwDir%/images'.

Parametry nemusí být jen řetězce nebo čísla, mohou také obsahovat pole:

parameters:
	mailer:
		host: smtp.example.com
		secure: ssl
		user: franta@gmail.com
	languages: [cs, en, de]

Na konkrétní klíč se odkážeme jako %mailer.user%.

Chcete-li zapsat řetězec začínající znakem @ nebo obsahující %, musíte znak escapovat zdvojením na @@ nebo %%.

Pokud potřebujete ve vašem kódu, například třídě, zjistit hodnotu jakékoliv parametru, tak jej do této třídy předejte. Například v konstruktoru. Neexistuje žádný globální objekt představující konfiguraci, kterého by se třídy dotazovaly na hodnoty parametrů. To by bylo porušením principu dependency injection.

PHP

Nastavení direktiv PHP. Přehled všech direktiv naleznete na php.net.

php:
	date.timezone: Europe/Prague

Routování

Základní nastavení:

routing:
	# zobrazit routovací panel v Tracy Bar?
	debugger: ...   # (bool) výchozí je true

	# serializuje router do DI kontejneru
	cache: ...      # (bool) výchozí je false

Routování obvykle definujeme ve třídě RouterFactory, omezenější alternativou je definice v konfiguraci pomocí dvojic maska: akce:

routing:
	routes:
		'detail/<id>': Admin:Home:default
		'<presenter>/<action>': Front:Home:default

Přístupová oprávnění

V konfiguraci lze definovat seznam uživatelů, a tak vytvořit jednoduchý authenticator (Nette\Security\SimpleAuthenticator). Protože se v konfiguraci uvádějí hesla v čitelné podobě, je tohle řešení vhodné pouze pro testovací účely.

security:
	# zobrazit panel uživatele v Tracy Bar?
	debugger: ...  # (bool) výchozí je true

	users:
		# jméno: heslo
		frantisek: tajneheslo

		# jméno, heslo, role a další data dostupná v identitě
		dobrota:
			password: tajneheslo
			roles: [admin]
			data: ...

Session

Základní nastavení sessions:

session:
	# zobrazit session panel v Tracy Bar?
	debugger: ...        # (bool) výchozí je false

	# doba neaktivity po které session vyexpiruje
	expiration: 14 days  # (string) výchozí je '3 hours'

	# startovat automaticky session po vytvoření kontejneru?
	# 'smart' startuje session pokud je již vytvořena
	autoStart: ...       # (bool|smart) výchozí je 'smart'

	# handler, služba implementující rozhraní SessionHandlerInterface
	handler: @handlerService

Nastavení cookieSecure se přebírá z nastavení HTTP cookie, můžete navíc upravit volby cookieDomain.

Atribut cookieDomain určuje, které domény mohou cookie přijímat. Není-li uveden, cookie přijímá stejná doména, jako ji nastavila, kromě subdomén. Pokud je cookieDomain zadán, jsou zahrnuty i subdomény. Proto je uvedení cookieDomain méně omezující než vynechání. Pokud je například nastaveno cookieDomain: nette.org, pak jsou cookies dostupné na subdoménách, jako je doc.nette.org. Téhož lze dosáhnout zápisem cookieDomain: domain.

session:
	# domény, které přijímají cookie
	cookieDomain: 'example.com'  # (string) výchozí je nenastaveno

Dále lze nastavovat všechny PHP session direktivy (ve formátu camelCase):

session:
	# 'session.name' zapíšeme jako 'name'
	name: MYID

	# 'session.save_path' zapíšeme jako 'savePath'
	savePath: "%tempDir%/sessions"

Tracy debugger

V konfiguraci lze nastavovat parametry Tracy a také přidávat nové panely do Tracy Bar. Tyto nastavení se aplikují teprve po vytvoření DI kontejneru, takže chyby vzniklé předtím je nemohou reflektovat.

Konfigurace logování chyb:

tracy:
	# e-mail, na který se posílají notifikace, že došlo k chybě
	email: dev@example.com           # (string|string[]) výchozí je nenastaveno

	# odesílatel e-mailu
	fromEmail: robot@example.com     # (string) výchozí je nenastaveno

	# použít pro odesílání e-mailů Nette mailer? (od Tracy 2.5)
	netteMailer: ...                 # (bool) výchozí je true

	# pro jaké úrovně chyb se loguje i BlueScreen?
	logSeverity: [E_WARNING, E_NOTICE]  # výchozí je []

Konfigurace chování funkce dump():

tracy:
	# maximální délka řetězce
	maxLength: 150             # (int) výchozí dle verze Tracy

	# maximální hloubka zanoření
	maxDepth: 10               # (int) výchozí dle verze Tracy

	# zobrazit místo, kde byla volána funkce dump()?
	showLocation: ...          # (bool) výchozí dle verze Tracy

Instalace rozšíření Tracy:

tracy:
	# přidá panely do Tracy Bar
	bar:
		- Nette\Bridges\DITracy\ContainerPanel
		- IncludePanel
		- XDebugHelper('myIdeKey')
		- MyPanel(@MyService)

	# přidá panely do BlueScreen
	blueScreen:
		- DoctrinePanel::renderException

Ostatní volby:

tracy:
	# ve vývojovém režimu zobrazí chyby typu notice nebo warning jako BlueScreen
	strictMode: ...           # (bool) výchozí je true

	# zobrazit umlčené (@) chybové hlášky?
	scream: ...               # (bool) výchozí je false

	# formát odkazu pro otevření v editoru
	editor: ....              # (string) výchozí je 'editor://open/?file=%file&line=%line'

	# cesta k šabloně s vlastní stránkou pro chybu 500
	errorTemplate: ...        # (string) výchozí je nenastaveno

	# zobrazit Tracy Bar?
	showBar: ...              # (bool) výchozí je true

	editorMapping:
		# originál: nová
		/var/www/html: /data/web
		/home/web: /srv/html

Služby a úpravy

Konfigurace je místem, kam umísťujeme definice vlastních služeb. Slouží k tomu sekce services, podrobný popis najdete v kapitole Služby.

Například takto může vypadat definice služby pojmenované database, což bude instance PDO:

services:
	database: PDO('mysql:host=127.0.0.1;dbname=test', root, password)

Dále je v DI kontejneru řada služeb, které přidaly vestavěné nebo vaše rozšíření. Definice těchto služeb lze v konfiguraci pozměnit. Třeba u služby application.application, což je standardně objekt Nette\Application\Application, můžeme změnit třídu:

services:
	application.application:
		factory: MyApplication
		alteration: true

Příznak alteration je informativní a říká, že jen modifikujeme existující službu.

Můžeme také doplnit setup:

services:
	application.application:
		factory: MyApplication
		alteration: true
		setup:
			- $onStartup = [@resource::init]

Službu přidanou rozšířením lze také z kontejneru odstranit:

services:
	cache.journal: false