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
verzió: 3.x