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áhozbool()
,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