Nette Documentation Preview

syntax
Szolgáltatás meghatározások
***************************

.[perex]
A konfiguráció az a hely, ahol utasítjuk a DI konténert, hogyan állítsa össze az egyes szolgáltatásokat, és hogyan kapcsolja össze őket más függőségekkel. A Nette egy nagyon világos és elegáns módot biztosít erre.

A NEON konfigurációs fájl `services` szakasza az a hely, ahol definiáljuk az egyéni szolgáltatásainkat és azok konfigurációit. Nézzünk egy egyszerű példát a `database` nevű szolgáltatás definiálására, amely a `PDO` osztály egy példányát képviseli:

```neon
services:
	database: PDO('sqlite::memory:')
```

Ez a konfiguráció a következő gyári metódust eredményezi a [DI konténerben |container]:

```php
public function createServiceDatabase(): PDO
{
	return new PDO('sqlite::memory:');
}
```

A szolgáltatásnevek lehetővé teszik, hogy a konfigurációs fájl más részeiben hivatkozzunk rájuk a `@serviceName` formátumban. Ha nincs szükség a szolgáltatás elnevezésére, akkor egyszerűen használhatunk egy felsorolásjelet:

```neon
services:
	- PDO('sqlite::memory:')
```

Egy szolgáltatás lekérdezéséhez a DI konténerből a `getService()` metódust használhatjuk a szolgáltatás nevével paraméterként, vagy a `getByType()` metódust a szolgáltatás típusával:

```php
$database = $container->getService('database');
$database = $container->getByType(PDO::class);
```


Szolgáltatás létrehozása .[#toc-service-creation]
=================================================

Leggyakrabban egy szolgáltatást egyszerűen egy adott osztály példányosításával hozunk létre. Például:

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

Ha a konfigurációt további kulcsokkal kell bővítenünk, a definíciót több sorban is kibővíthetjük:

```neon
services:
	database:
		create: PDO('sqlite::memory:')
		setup: ...
```

A `create` kulcsnak van egy aliasa: `factory`, mindkét változat gyakori a gyakorlatban. Javasoljuk azonban a `create` használatát.

A konstruktor argumentumai vagy a létrehozási módszer alternatívaként a `arguments` kulcsban is leírhatók:

```neon
services:
	database:
		create: PDO
		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
```

A szolgáltatásokat nem csak egy osztály egyszerű példányosításával kell létrehozni; létrejöhetnek statikus metódusok vagy más szolgáltatások metódusainak hívásából is:

```neon
services:
	database: DatabaseFactory::create()
	router: @routerFactory::create()
```

Megjegyezzük, hogy az egyszerűség kedvéért a `->` helyett a `::` használjuk, lásd a [kifejezés eszközeit |#expression means]. Ezeket a gyári metódusokat generáljuk:

```php
public function createServiceDatabase(): PDO
{
	return DatabaseFactory::create();
}

public function createServiceRouter(): RouteList
{
	return $this->getService('routerFactory')->create();
}
```

A DI konténernek tudnia kell a létrehozott szolgáltatás típusát. Ha olyan metódussal hozunk létre egy szolgáltatást, amelynek nincs megadott visszatérési típusa, akkor ezt a típust kifejezetten meg kell említenünk a konfigurációban:

```neon
services:
	database:
		create: DatabaseFactory::create()
		type: PDO
```


Érvek .[#toc-arguments]
=======================

A konstruktoroknak és metódusoknak a hagyományos PHP-hoz nagyon hasonló módon adunk át argumentumokat:

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

A jobb olvashatóság érdekében az argumentumokat külön sorokban is felsorolhatjuk. Ebben a formátumban a vesszők használata opcionális:

```neon
services:
	database: PDO(
		'mysql:host=127.0.0.1;dbname=test'
		root
		secret
	)
```

Az argumentumokat el is nevezhetjük, így nem kell aggódnunk a sorrendjük miatt:

```neon
services:
	database: PDO(
		username: root
		password: secret
		dsn: 'mysql:host=127.0.0.1;dbname=test'
	)
```

Ha bizonyos argumentumokat el akar hagyni, és azok alapértelmezett értékét kívánja használni, vagy egy szolgáltatást [automatikus bekötéssel |autowiring] szeretne beilleszteni, használjon aláhúzást:

```neon
services:
	foo: Foo(_, %appDir%)
```

Az argumentumok lehetnek szolgáltatások, paraméterek és még sok más, lásd a [kifejezés eszközeit |#expression means].


Beállítás .[#toc-setup]
=======================

A `setup` szakaszban definiáljuk azokat a metódusokat, amelyeket a szolgáltatás létrehozásakor meg kell hívni.

```neon
services:
	database:
		create: PDO(%dsn%, %user%, %password%)
		setup:
			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
```

PHP nyelven ez így nézne ki:

```php
public function createServiceDatabase(): PDO
{
	$service = new PDO('...', '...', '...');
	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	return $service;
}
```

A metódushívások mellett értékeket is átadhat a tulajdonságoknak. Egy elem hozzáadása egy tömbhöz szintén támogatott, de azt idézőjelek közé kell zárni, hogy ne ütközzön a NEON szintaxissal:

```neon
services:
	foo:
		create: Foo
		setup:
			- $value = 123
			- '$onClick[]' = [@bar, clickHandler]
```

PHP-ben ez a következőképpen hangzana:

```php
public function createServiceFoo(): Foo
{
	$service = new Foo;
	$service->value = 123;
	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
	return $service;
}
```

A beállításban statikus módszereket vagy más szolgáltatások metódusait is meghívhatja. Ha az aktuális szolgáltatást kell átadni argumentumként, használja a `@self` címet:

```neon
services:
	foo:
		create: Foo
		setup:
			- My\Helpers::initializeFoo(@self)
			- @anotherService::setFoo(@self)
```

Vegye figyelembe, hogy az egyszerűség kedvéért a `->` helyett a `::`, lásd a [kifejezés eszközeit |#expression means]. Ez a következő gyári metódust generálja:

```php
public function createServiceFoo(): Foo
{
	$service = new Foo;
	My\Helpers::initializeFoo($service);
	$this->getService('anotherService')->setFoo($service);
	return $service;
}
```


Kifejezés Eszközök .[#toc-expression-means]
===========================================

A Nette DI kivételesen gazdag kifejezési lehetőségeket biztosít számunkra, lehetővé téve számunkra, hogy szinte bármit megfogalmazzunk. A konfigurációs fájlokban használhatunk [paramétereket |configuration#parameters]:

```neon
# paraméter
%wwwDir%

# érték egy paraméterkulcs alatt
%mailer.user%

# paraméter egy karakterláncon belül
'%wwwDir%/images'
```

Objektumokat is létrehozhatunk, metódusokat és függvényeket hívhatunk:

```neon
# hozzon létre egy objektumot
DateTime()

# statikus metódus hívása
Collator::create(%locale%)

# PHP függvény hívása
::getenv(DB_USER)
```

A szolgáltatásokra a nevük vagy a típusuk alapján hivatkozhatunk:

```neon
# szolgáltatás név szerint
@database

# szolgáltatás típusa szerint
@Nette\Database\Connection
```

Első osztályú hívható szintaxis használata: .{data-version:3.2.0}

```neon
# creating a callback, equivalent to [@user, logout]
@user::logout(...)
```

Konstanciák használata:

```neon
# osztálykonstans
FilesystemIterator::SKIP_DOTS

# globális konstans, amelyet a PHP konstans() függvényével kapunk.
::constant(PHP_VERSION)
```

A metódushívások láncolhatók, akárcsak a PHP-ban. Az egyszerűség kedvéért a `->` helyett a `::` címet használjuk:

```neon
DateTime()::format('Y-m-d')
# PHP: (new DateTime())->format('Y-m-d')

@http.request::getUrl()::getHost()
# PHP: http.request')->getUrl()->getHost()
```

Ezek a kifejezések bárhol használhatók a [szolgáltatások létrehozásakor |#Service Creation], az [argumentumokban |#Arguments], a [beállítási |#setup] szakaszban vagy a [paraméterekben |configuration#parameters]:

```neon
parameters:
	ipAddress: @http.request::getRemoteAddress()

services:
	database:
		create: DatabaseFactory::create( @anotherService::getDsn() )
		setup:
			- initialize( ::getenv('DB_USER') )
```


Különleges funkciók .[#toc-special-functions]
---------------------------------------------

A konfigurációs fájlokon belül használhatja ezeket a speciális funkciókat:

- `not()` az érték negációjához
- `bool()`, `int()`, `float()`, `string()` a veszteségmentes típusváltáshoz.
- `typed()` a megadott típusú szolgáltatások tömbjének létrehozásához.
- `tagged()` egy adott címkével rendelkező összes szolgáltatás tömbjének létrehozásához.

```neon
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)
```

A PHP hagyományos típuskiosztásához képest, mint például a `(int)`, a veszteségmentes típuskiosztás kivételt dob a nem numerikus értékek esetén.

A `typed()` függvény egy adott típusú (osztály vagy interfész) összes szolgáltatásának tömbjét hozza létre. Kizárja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva. Több típus is megadható, vesszővel elválasztva.

```neon
services:
	- BarsDependent( typed(Bar) )
```

Az [autowiring |autowiring#Collection of Services] használatával egy adott típusú szolgáltatások tömbjét is automatikusan átadhatja argumentumként.

A `tagged()` függvény létrehozza a megadott címkével rendelkező összes szolgáltatás tömbjét. Több címke is felsorolható, vesszővel elválasztva.

```neon
services:
	- LoggersDependent( tagged(logger) )
```


Autowiring .[#toc-autowiring]
=============================

A `autowired` billentyűvel módosíthatja egy adott szolgáltatás autowiring viselkedését. További részletekért lásd [az autowiring fejezetet |autowiring].

```neon
services:
	foo:
		create: Foo
		autowired: false     # a foo szolgáltatás ki van zárva az automatikus bekötésből
```


Címkék .[#toc-tags]
===================

A címkék a szolgáltatások kiegészítő információkkal való kiegészítésére szolgálnak. Egy vagy több címkét rendelhet egy szolgáltatáshoz:

```neon
services:
	foo:
		create: Foo
		tags:
			- cached
```

A címkék értékeket is hordozhatnak:

```neon
services:
	foo:
		create: Foo
		tags:
			logger: monolog.logger.event
```

A `tagged()` funkcióval lekérdezheti az adott címkékkel rendelkező összes szolgáltatást:

```neon
services:
	- LoggersDependent( tagged(logger) )
```

A DI konténerben a `findByTag()` metódus segítségével megkaphatja az összes, egy adott címkével rendelkező szolgáltatás nevét:

```php
$names = $container->findByTag('logger');
// $names egy tömb, amely a szolgáltatás nevét és a tag értékét tartalmazza.
// pl. ['foo' => 'monolog.logger.event', ...]
```


Injektálás mód .[#toc-inject-mode]
==================================

A `inject: true` jelző használata aktiválja a függőségek átadását nyilvános változókon keresztül az [inject |best-practices:inject-method-attribute#Inject Attributes] megjegyzésekkel és az [inject*() |best-practices:inject-method-attribute#inject Methods] metódusokkal.

```neon
services:
	articles:
		create: App\Model\Articles
		inject: true
```

Alapértelmezés szerint a `inject` csak az előadók esetében van aktiválva.


Szolgáltatás módosítások .[#toc-service-modifications]
======================================================

A DI konténer számos beépített vagy [felhasználói bővítéssel |#extensions] hozzáadott szolgáltatást tartalmaz. Ezeknek a szolgáltatásoknak a definícióit közvetlenül a konfigurációban módosíthatja. Például megváltoztathatja a `application.application` szolgáltatás osztályát, amely a hagyományos `Nette\Application\Application`, másra:

```neon
services:
	application.application:
		create: MyApplication
		alteration: true
```

A `alteration` jelző tájékoztató jellegű, jelzi, hogy csupán egy meglévő szolgáltatást módosítunk.

Kiegészíthetjük a beállítást is:

```neon
services:
	application.application:
		create: MyApplication
		alteration: true
		setup:
			- '$onStartup[]' = [@resource, init]
```

Itt jön jól a `reset`:

```neon
services:
	application.application:
		create: MyApplication
		alteration: true
		reset:
			- arguments
			- setup
			- tags
```

Ha egy bővítmény által hozzáadott szolgáltatást szeretne eltávolítani, akkor ezt a következőképpen teheti meg:

```neon
services:
	cache.journal: false
```

Szolgáltatás meghatározások

A konfiguráció az a hely, ahol utasítjuk a DI konténert, hogyan állítsa össze az egyes szolgáltatásokat, és hogyan kapcsolja össze őket más függőségekkel. A Nette egy nagyon világos és elegáns módot biztosít erre.

A NEON konfigurációs fájl services szakasza az a hely, ahol definiáljuk az egyéni szolgáltatásainkat és azok konfigurációit. Nézzünk egy egyszerű példát a database nevű szolgáltatás definiálására, amely a PDO osztály egy példányát képviseli:

services:
	database: PDO('sqlite::memory:')

Ez a konfiguráció a következő gyári metódust eredményezi a DI konténerben:

public function createServiceDatabase(): PDO
{
	return new PDO('sqlite::memory:');
}

A szolgáltatásnevek lehetővé teszik, hogy a konfigurációs fájl más részeiben hivatkozzunk rájuk a @serviceName formátumban. Ha nincs szükség a szolgáltatás elnevezésére, akkor egyszerűen használhatunk egy felsorolásjelet:

services:
	- PDO('sqlite::memory:')

Egy szolgáltatás lekérdezéséhez a DI konténerből a getService() metódust használhatjuk a szolgáltatás nevével paraméterként, vagy a getByType() metódust a szolgáltatás típusával:

$database = $container->getService('database');
$database = $container->getByType(PDO::class);

Szolgáltatás létrehozása

Leggyakrabban egy szolgáltatást egyszerűen egy adott osztály példányosításával hozunk létre. Például:

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

Ha a konfigurációt további kulcsokkal kell bővítenünk, a definíciót több sorban is kibővíthetjük:

services:
	database:
		create: PDO('sqlite::memory:')
		setup: ...

A create kulcsnak van egy aliasa: factory, mindkét változat gyakori a gyakorlatban. Javasoljuk azonban a create használatát.

A konstruktor argumentumai vagy a létrehozási módszer alternatívaként a arguments kulcsban is leírhatók:

services:
	database:
		create: PDO
		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]

A szolgáltatásokat nem csak egy osztály egyszerű példányosításával kell létrehozni; létrejöhetnek statikus metódusok vagy más szolgáltatások metódusainak hívásából is:

services:
	database: DatabaseFactory::create()
	router: @routerFactory::create()

Megjegyezzük, hogy az egyszerűség kedvéért a -> helyett a :: használjuk, lásd a kifejezés eszközeit. Ezeket a gyári metódusokat generáljuk:

public function createServiceDatabase(): PDO
{
	return DatabaseFactory::create();
}

public function createServiceRouter(): RouteList
{
	return $this->getService('routerFactory')->create();
}

A DI konténernek tudnia kell a létrehozott szolgáltatás típusát. Ha olyan metódussal hozunk létre egy szolgáltatást, amelynek nincs megadott visszatérési típusa, akkor ezt a típust kifejezetten meg kell említenünk a konfigurációban:

services:
	database:
		create: DatabaseFactory::create()
		type: PDO

Érvek

A konstruktoroknak és metódusoknak a hagyományos PHP-hoz nagyon hasonló módon adunk át argumentumokat:

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

A jobb olvashatóság érdekében az argumentumokat külön sorokban is felsorolhatjuk. Ebben a formátumban a vesszők használata opcionális:

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

Az argumentumokat el is nevezhetjük, így nem kell aggódnunk a sorrendjük miatt:

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

Ha bizonyos argumentumokat el akar hagyni, és azok alapértelmezett értékét kívánja használni, vagy egy szolgáltatást automatikus bekötéssel szeretne beilleszteni, használjon aláhúzást:

services:
	foo: Foo(_, %appDir%)

Az argumentumok lehetnek szolgáltatások, paraméterek és még sok más, lásd a kifejezés eszközeit.

Beállítás

A setup szakaszban definiáljuk azokat a metódusokat, amelyeket a szolgáltatás létrehozásakor meg kell hívni.

services:
	database:
		create: PDO(%dsn%, %user%, %password%)
		setup:
			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)

PHP nyelven ez így nézne ki:

public function createServiceDatabase(): PDO
{
	$service = new PDO('...', '...', '...');
	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	return $service;
}

A metódushívások mellett értékeket is átadhat a tulajdonságoknak. Egy elem hozzáadása egy tömbhöz szintén támogatott, de azt idézőjelek közé kell zárni, hogy ne ütközzön a NEON szintaxissal:

services:
	foo:
		create: Foo
		setup:
			- $value = 123
			- '$onClick[]' = [@bar, clickHandler]

PHP-ben ez a következőképpen hangzana:

public function createServiceFoo(): Foo
{
	$service = new Foo;
	$service->value = 123;
	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
	return $service;
}

A beállításban statikus módszereket vagy más szolgáltatások metódusait is meghívhatja. Ha az aktuális szolgáltatást kell átadni argumentumként, használja a @self címet:

services:
	foo:
		create: Foo
		setup:
			- My\Helpers::initializeFoo(@self)
			- @anotherService::setFoo(@self)

Vegye figyelembe, hogy az egyszerűség kedvéért a -> helyett a ::, lásd a kifejezés eszközeit. Ez a következő gyári metódust generálja:

public function createServiceFoo(): Foo
{
	$service = new Foo;
	My\Helpers::initializeFoo($service);
	$this->getService('anotherService')->setFoo($service);
	return $service;
}

Kifejezés Eszközök

A Nette DI kivételesen gazdag kifejezési lehetőségeket biztosít számunkra, lehetővé téve számunkra, hogy szinte bármit megfogalmazzunk. A konfigurációs fájlokban használhatunk paramétereket:

# paraméter
%wwwDir%

# érték egy paraméterkulcs alatt
%mailer.user%

# paraméter egy karakterláncon belül
'%wwwDir%/images'

Objektumokat is létrehozhatunk, metódusokat és függvényeket hívhatunk:

# hozzon létre egy objektumot
DateTime()

# statikus metódus hívása
Collator::create(%locale%)

# PHP függvény hívása
::getenv(DB_USER)

A szolgáltatásokra a nevük vagy a típusuk alapján hivatkozhatunk:

# szolgáltatás név szerint
@database

# szolgáltatás típusa szerint
@Nette\Database\Connection

Első osztályú hívható szintaxis használata:

# creating a callback, equivalent to [@user, logout]
@user::logout(...)

Konstanciák használata:

# osztálykonstans
FilesystemIterator::SKIP_DOTS

# globális konstans, amelyet a PHP konstans() függvényével kapunk.
::constant(PHP_VERSION)

A metódushívások láncolhatók, akárcsak a PHP-ban. Az egyszerűség kedvéért a -> helyett a :: címet használjuk:

DateTime()::format('Y-m-d')
# PHP: (new DateTime())->format('Y-m-d')

@http.request::getUrl()::getHost()
# PHP: http.request')->getUrl()->getHost()

Ezek a kifejezések bárhol használhatók a szolgáltatások létrehozásakor, az argumentumokban, a beállítási szakaszban vagy a paraméterekben:

parameters:
	ipAddress: @http.request::getRemoteAddress()

services:
	database:
		create: DatabaseFactory::create( @anotherService::getDsn() )
		setup:
			- initialize( ::getenv('DB_USER') )

Különleges funkciók

A konfigurációs fájlokon belül használhatja ezeket a speciális funkciókat:

  • not() az érték negációjához
  • bool(), int(), float(), string() a veszteségmentes típusváltáshoz.
  • typed() a megadott típusú szolgáltatások tömbjének létrehozásához.
  • tagged() egy adott címkével rendelkező összes szolgáltatás tömbjének létrehozásához.
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)

A PHP hagyományos típuskiosztásához képest, mint például a (int), a veszteségmentes típuskiosztás kivételt dob a nem numerikus értékek esetén.

A typed() függvény egy adott típusú (osztály vagy interfész) összes szolgáltatásának tömbjét hozza létre. Kizárja azokat a szolgáltatásokat, amelyeknél az automatikus kapcsolás ki van kapcsolva. Több típus is megadható, vesszővel elválasztva.

services:
	- BarsDependent( typed(Bar) )

Az autowiring használatával egy adott típusú szolgáltatások tömbjét is automatikusan átadhatja argumentumként.

A tagged() függvény létrehozza a megadott címkével rendelkező összes szolgáltatás tömbjét. Több címke is felsorolható, vesszővel elválasztva.

services:
	- LoggersDependent( tagged(logger) )

Autowiring

A autowired billentyűvel módosíthatja egy adott szolgáltatás autowiring viselkedését. További részletekért lásd az autowiring fejezetet.

services:
	foo:
		create: Foo
		autowired: false     # a foo szolgáltatás ki van zárva az automatikus bekötésből

Címkék

A címkék a szolgáltatások kiegészítő információkkal való kiegészítésére szolgálnak. Egy vagy több címkét rendelhet egy szolgáltatáshoz:

services:
	foo:
		create: Foo
		tags:
			- cached

A címkék értékeket is hordozhatnak:

services:
	foo:
		create: Foo
		tags:
			logger: monolog.logger.event

A tagged() funkcióval lekérdezheti az adott címkékkel rendelkező összes szolgáltatást:

services:
	- LoggersDependent( tagged(logger) )

A DI konténerben a findByTag() metódus segítségével megkaphatja az összes, egy adott címkével rendelkező szolgáltatás nevét:

$names = $container->findByTag('logger');
// $names egy tömb, amely a szolgáltatás nevét és a tag értékét tartalmazza.
// pl. ['foo' => 'monolog.logger.event', ...]

Injektálás mód

A inject: true jelző használata aktiválja a függőségek átadását nyilvános változókon keresztül az inject megjegyzésekkel és az inject*() metódusokkal.

services:
	articles:
		create: App\Model\Articles
		inject: true

Alapértelmezés szerint a inject csak az előadók esetében van aktiválva.

Szolgáltatás módosítások

A DI konténer számos beépített vagy felhasználói bővítéssel hozzáadott szolgáltatást tartalmaz. Ezeknek a szolgáltatásoknak a definícióit közvetlenül a konfigurációban módosíthatja. Például megváltoztathatja a application.application szolgáltatás osztályát, amely a hagyományos Nette\Application\Application, másra:

services:
	application.application:
		create: MyApplication
		alteration: true

A alteration jelző tájékoztató jellegű, jelzi, hogy csupán egy meglévő szolgáltatást módosítunk.

Kiegészíthetjük a beállítást is:

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

Itt jön jól a reset:

services:
	application.application:
		create: MyApplication
		alteration: true
		reset:
			- arguments
			- setup
			- tags

Ha egy bővítmény által hozzáadott szolgáltatást szeretne eltávolítani, akkor ezt a következőképpen teheti meg:

services:
	cache.journal: false