Opredelitve storitev
Konfiguracija je mesto, kjer vsebniku DI naročimo, kako naj sestavi posamezne storitve in kako naj jih poveže z drugimi odvisnostmi. Nette ponuja zelo jasen in eleganten način za doseganje tega cilja.
V razdelku services
v konfiguracijski datoteki NEON opredelimo svoje storitve po meri in njihove konfiguracije.
Oglejmo si preprost primer opredelitve storitve z imenom database
, ki predstavlja primerek razreda
PDO
:
services:
database: PDO('sqlite::memory:')
Rezultat te konfiguracije je naslednja tovarniška metoda v vsebniku DI:
public function createServiceDatabase(): PDO
{
return new PDO('sqlite::memory:');
}
Imena storitev nam omogočajo sklicevanje nanje v drugih delih konfiguracijske datoteke v obliki @serviceName
.
Če storitve ni treba poimenovati, lahko preprosto uporabimo točko:
services:
- PDO('sqlite::memory:')
Za pridobitev storitve iz vsebnika DI lahko uporabimo metodo getService()
z imenom storitve kot parametrom ali
metodo getByType()
s tipom storitve:
$database = $container->getService('database');
$database = $container->getByType(PDO::class);
Ustvarjanje storitev
Najpogosteje ustvarimo storitev tako, da instanciramo določen razred. Na primer:
services:
database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
Če moramo konfiguracijo razširiti z dodatnimi ključi, lahko definicijo razširimo v več vrstic:
services:
database:
create: PDO('sqlite::memory:')
setup: ...
Ključ create
ima vzdevek factory
, obe različici sta v praksi pogosti. Vendar priporočamo uporabo
ključa create
.
Argumente konstruktorja ali metodo ustvarjanja lahko alternativno zapišete v ključu arguments
:
services:
database:
create: PDO
arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
Storitve niso nujno ustvarjene samo z enostavno instanciacijo razreda; lahko so tudi posledica klica statičnih metod ali metod drugih storitev:
services:
database: DatabaseFactory::create()
router: @routerFactory::create()
Upoštevajte, da zaradi enostavnosti namesto ->
uporabljamo ::
, glej izrazna sredstva. Te tovarniške metode so ustvarjene:
public function createServiceDatabase(): PDO
{
return DatabaseFactory::create();
}
public function createServiceRouter(): RouteList
{
return $this->getService('routerFactory')->create();
}
vsebnik DI mora poznati vrsto ustvarjene storitve. Če ustvarimo storitev z metodo, ki nima določene vrnitvene vrste, moramo to vrsto izrecno navesti v konfiguraciji:
services:
database:
create: DatabaseFactory::create()
type: PDO
Argumenti
Argumente konstruktorjem in metodam posredujemo na zelo podoben način kot v običajnem jeziku PHP:
services:
database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
Za boljšo berljivost lahko argumente navedemo v ločenih vrsticah. V tej obliki je uporaba vejic neobvezna:
services:
database: PDO(
'mysql:host=127.0.0.1;dbname=test'
root
secret
)
Argumente lahko tudi poimenujete, kar vam omogoča, da se ne ukvarjate z njihovim vrstnim redom:
services:
database: PDO(
username: root
password: secret
dsn: 'mysql:host=127.0.0.1;dbname=test'
)
Če želite določene argumente izpustiti in uporabiti njihove privzete vrednosti ali vstaviti storitev prek samodejnega napeljevanja, uporabite podčrtaj:
services:
foo: Foo(_, %appDir%)
Argumenti so lahko storitve, parametri in še veliko več, glejte izrazna sredstva.
Nastavitev
V razdelku setup
opredelimo metode, ki jih je treba poklicati pri ustvarjanju storitve.
services:
database:
create: PDO(%dsn%, %user%, %password%)
setup:
- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
V jeziku PHP bi bilo to videti takole:
public function createServiceDatabase(): PDO
{
$service = new PDO('...', '...', '...');
$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $service;
}
Poleg klicev metod lahko lastnostim posredujete tudi vrednosti. Podprto je tudi dodajanje elementa v polje, vendar ga morate zapreti v narekovaje, da ne pride do kolizije s sintakso NEON:
services:
foo:
create: Foo
setup:
- $value = 123
- '$onClick[]' = [@bar, clickHandler]
V jeziku PHP bi to pomenilo:
public function createServiceFoo(): Foo
{
$service = new Foo;
$service->value = 123;
$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
return $service;
}
V nastavitvi lahko kličete tudi statične metode ali metode drugih storitev. Če morate kot argument posredovati trenutno
storitev, uporabite @self
:
services:
foo:
create: Foo
setup:
- My\Helpers::initializeFoo(@self)
- @anotherService::setFoo(@self)
Upoštevajte, da zaradi enostavnosti namesto ->
uporabimo ::
, glejte izrazna sredstva. To ustvari naslednjo tovarniško metodo:
public function createServiceFoo(): Foo
{
$service = new Foo;
My\Helpers::initializeFoo($service);
$this->getService('anotherService')->setFoo($service);
return $service;
}
Sredstva za izražanje
Nette DI nam zagotavlja izjemno bogate izrazne možnosti, s katerimi lahko izrazimo skoraj vse. V konfiguracijskih datotekah lahko uporabljamo parametre:
# parameter
%wwwDir%
# vrednost pod ključem parametra
%mailer.user%
# parameter v nizu
'%wwwDir%/images'
Prav tako lahko ustvarjamo predmete, kličemo metode in funkcije:
# ustvariti predmet
DateTime()
# klic statične metode
Collator::create(%locale%)
# klic funkcije PHP
::getenv(DB_USER)
Na storitve se lahko sklicujemo po imenu ali vrsti:
# storitev po imenu
@database
# storitev po vrsti
@Nette\Database\Connection
Uporabite sintakso prvega razreda za klicanje:
# creating a callback, equivalent to [@user, logout]
@user::logout(...)
Uporabite konstante:
# razred stalnica
FilesystemIterator::SKIP_DOTS
# globalna konstanta, pridobljena s funkcijo PHP constant()
::constant(PHP_VERSION)
Tako kot v PHP lahko klice metod verižite. Zaradi preprostosti namesto ->
uporabimo ::
:
DateTime()::format('Y-m-d')
# PHP: (new DateTime())->format('Y-m-d')
@http.request::getUrl()::getHost()
# PHP: $this->getService('http.request')->getUrl()->getHost()
Te izraze lahko pri ustvarjanju storitev uporabite kjer koli, v argumentih, v nastavitvenem delu ali parametrih:
parameters:
ipAddress: @http.request::getRemoteAddress()
services:
database:
create: DatabaseFactory::create( @anotherService::getDsn() )
setup:
- initialize( ::getenv('DB_USER') )
Posebne funkcije
V konfiguracijskih datotekah lahko uporabite te posebne funkcije:
not()
za zanikanje vrednostibool()
,int()
,float()
,string()
za brezizgubno ulivanje tipovtyped()
za ustvarjanje polja vseh storitev določenega tipatagged()
za ustvarjanje polja vseh storitev z določeno oznako
services:
- Foo(
id: int(::getenv('ProjectId'))
productionMode: not(%debugMode%)
)
V primerjavi z običajnim tipiziranjem v PHP, kot je (int)
, bo brezizgubno tipiziranje vrglo izjemo za
neštevilčne vrednosti.
Funkcija typed()
ustvari polje vseh storitev določene vrste (razreda ali vmesnika). Izključuje storitve
z izklopljenim samodejnim vgrajevanjem. Določite lahko več vrst, ki jih ločite z vejicami.
services:
- BarsDependent( typed(Bar) )
Kot argument lahko samodejno posredujete tudi polje storitev določene vrste z uporabo samodejnega napeljevanja.
Funkcija tagged()
ustvari polje vseh storitev z določeno oznako. Navedete lahko več oznak, ki jih ločite
z vejicami.
services:
- LoggersDependent( tagged(logger) )
Avtomatska napeljava
Ključ autowired
omogoča spreminjanje obnašanja samodejnega ožičenja za določeno storitev. Za več
podrobnosti glejte poglavje o samodejnem ožičenju.
services:
foo:
create: Foo
autowired: false # storitev foo je izključena iz samodejnega ožičenja
Lene storitve
Leno nalaganje je tehnika, ki odloži ustvarjanje storitve, dokler je ta dejansko potrebna. Leno ustvarjanje storitev lahko omogočite globalno v konfiguraciji za vse storitve hkrati. Za posamezne storitve lahko to obnašanje prekrijete:
services:
foo:
create: Foo
lazy: false
Če je storitev opredeljena kot lena, bo zahteva iz vsebnika DI vrnila poseben objekt posrednika. Ta posrednik je videti in se obnaša kot dejanska storitev, vendar se prava inicializacija (klic konstruktorja in nastavitev) izvede šele ob prvem klicu katere koli njene metode ali lastnosti.
Leno nalaganje je mogoče uporabiti le za uporabniško definirane razrede, ne pa tudi za notranje razrede PHP. Zahteva PHP 8.4 ali novejšo različico.
Oznake
Oznake se uporabljajo za dodajanje dodatnih informacij storitvam. Storitvi lahko dodelite eno ali več oznak:
services:
foo:
create: Foo
tags:
- cached
Oznake lahko nosijo tudi vrednosti:
services:
foo:
create: Foo
tags:
logger: monolog.logger.event
Če želite priklicati vse storitve z določenimi oznakami, lahko uporabite funkcijo tagged()
:
services:
- LoggersDependent( tagged(logger) )
V vsebniku DI lahko z metodo findByTag()
pridobite imena vseh storitev z določeno oznako:
$names = $container->findByTag('logger');
// $names je polje, ki vsebuje ime storitve in vrednost oznake
// npr. ['foo' => 'monolog.logger.event', ...]
Način vbrizgavanja
Uporaba oznake inject: true
aktivira posredovanje odvisnosti prek javnih spremenljivk z opombo inject in metodami inject*( ).
services:
articles:
create: App\Model\Articles
inject: true
Privzeto je funkcija inject
aktivirana samo za predstavnike.
Spremembe storitev
Vsebnik DI vsebuje številne storitve, ki so dodane z vgrajenimi ali uporabniškimi
razširitvami. Definicije teh storitev lahko spreminjate neposredno v konfiguraciji. Tako lahko na primer spremenite razred
storitve application.application
, ki je običajno Nette\Application\Application
, v drug razred:
services:
application.application:
create: MyApplication
alteration: true
Oznaka alteration
je informativna in pomeni, da zgolj spreminjamo obstoječo storitev.
Nastavitev lahko tudi dopolnimo:
services:
application.application:
create: MyApplication
alteration: true
setup:
- '$onStartup[]' = [@resource, init]
Pri prepisovanju storitve boste morda želeli odstraniti prvotne argumente, nastavitvene elemente ali oznake, pri čemer vam
pride prav reset
:
services:
application.application:
create: MyApplication
alteration: true
reset:
- arguments
- setup
- tags
Če želite odstraniti storitev, ki jo je dodala razširitev, lahko to storite na naslednji način:
services:
cache.journal: false