Definiții ale serviciilor
Configurația este locul în care se plasează definițiile serviciilor personalizate. Acest lucru se face în
secțiunea services
.
De exemplu, astfel creăm un serviciu numit database
, care va fi o instanță a clasei PDO
:
services:
database: PDO('sqlite::memory:')
Denumirea serviciilor este utilizată pentru a ne permite să le referim la acestea. În cazul în care un serviciu nu este menționat, nu este necesar să îl denumim. Prin urmare, folosim doar un punct în loc de un nume:
services:
- PDO('sqlite::memory:') # serviciu anonim
O intrare pe o singură linie poate fi împărțită în mai multe linii pentru a permite adăugarea de chei suplimentare,
cum ar fi configurare. Pseudonimul pentru tasta create:
este factory:
.
services:
database:
create: PDO('sqlite::memory:')
setup: ...
Apoi, recuperăm serviciul din containerul DI folosind metoda getService()
după nume sau, mai bine, metoda
getByType()
după tip:
$database = $container->getService('database');
$database = $container->getByType(PDO::class);
Crearea unui serviciu
Cel mai adesea, creăm un serviciu prin simpla creare a unei instanțe a unei clase:
services:
database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
Ceea ce va genera o metodă factory în containerul DI:
public function createServiceDatabase(): PDO
{
return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
}
Alternativ, o cheie arguments
poate fi utilizată pentru a transmite argumente:
services:
database:
create: PDO
arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
O metodă statică poate crea, de asemenea, un serviciu:
services:
database: My\Database::create(root, secret)
Corespunde codului PHP:
public function createServiceDatabase(): PDO
{
return My\Database::create('root', 'secret');
}
O metodă statică My\Database::create()
se presupune că are o valoare de returnare definită pe care
containerul DI trebuie să o cunoască. Dacă nu o are, scriem tipul în configurație:
services:
database:
create: My\Database::create(root, secret)
type: PDO
Nette DI vă oferă facilități de exprimare extrem de puternice pentru a scrie aproape orice. De exemplu, pentru a face referire la un alt serviciu și a apela metoda acestuia. Pentru simplificare, se folosește
::
în loc de ->
.
services:
routerFactory: App\Router\Factory
router: @routerFactory::create()
Corespunde codului PHP:
public function createServiceRouterFactory(): App\Router\Factory
{
return new App\Router\Factory;
}
public function createServiceRouter(): Router
{
return $this->getService('routerFactory')->create();
}
Apelurile la metode pot fi înlănțuite ca în PHP:
services:
foo: FooFactory::build()::get()
Corespunde codului PHP:
public function createServiceFoo()
{
return FooFactory::build()->get();
}
Argumente
Parametrii numiți pot fi utilizați și pentru a transmite argumente:
services:
database: PDO(
'mysql:host=127.0.0.1;dbname=test' # pozițional
username: root # numit
password: secret # numit
)
Utilizarea virgulelor este opțională atunci când argumentele sunt împărțite pe mai multe linii.
Bineînțeles, putem folosi și alte servicii sau parametri ca argumente:
services:
- Foo(@anotherService, %appDir%)
Corespunde codului PHP:
public function createService01(): Foo
{
return new Foo($this->getService('anotherService'), '...');
}
Dacă primul argument este autowired și doriți să îl
specificați pe al doilea, omiteți-l pe primul cu _
character, for example Foo(_, %appDir%)
. Sau, mai
bine, treceți doar al doilea argument ca parametru numit, de exemplu Foo(path: %appDir%)
.
Nette DI și formatul NEON vă oferă facilități expresive extrem de puternice pentru a scrie aproape orice. Astfel, un argument poate fi un obiect nou creat, puteți apela metode statice, metode ale altor servicii sau chiar funcții globale folosind o notație specială:
services:
analyser: My\Analyser(
FilesystemIterator(%appDir%) # creați un obiect
DateTime::createFromFormat('Y-m-d') # apelați metoda statică
@anotherService # trecerea unui alt serviciu
@http.request::getRemoteAddress() # apelarea unei alte metode de serviciu
::getenv(NetteMode) # apelarea unei funcții globale
)
Corespunde codului PHP:
public function createServiceAnalyser(): My\Analyser
{
return new My\Analyser(
new FilesystemIterator('...'),
DateTime::createFromFormat('Y-m-d'),
$this->getService('anotherService'),
$this->getService('http.request')->getRemoteAddress(),
getenv('NetteMode')
);
}
Funcții speciale
Puteți utiliza, de asemenea, funcții speciale în argumente pentru a transforma sau nega valori:
not(%arg%)
negareabool(%arg%)
cast fără pierderi în boolint(%arg%)
lossless cast to intfloat(%arg%)
lossless cast to floatstring(%arg%)
lossless cast to string
services:
- Foo(
id: int(::getenv('ProjectId'))
productionMode: not(%debugMode%)
)
Rescrierea fără pierderi diferă de rescrierea normală din PHP, de exemplu, folosind (int)
, prin faptul că
aruncă o excepție pentru valorile nenumerice.
Mai multe servicii pot fi trecute ca argumente. Un tablou al tuturor serviciilor de un anumit tip (de exemplu, clasă sau
interfață) este creat de funcția typed()
. Funcția va omite serviciile care au cablarea automată dezactivată și
pot fi specificate mai multe tipuri separate prin virgulă.
services:
- BarsDependent( typed(Bar) )
De asemenea, puteți transmite automat o matrice de servicii utilizând autowiring.
O matrice a tuturor serviciilor cu o anumită etichetă este creată de funcția
tagged()
. Se pot specifica mai multe etichete separate prin virgulă.
services:
- LoggersDependent( tagged(logger) )
Servicii de referință
Serviciile individuale sunt referite folosind caracterul @
and name, so for example @database
:
services:
- create: Foo(@database)
setup:
- setCacheStorage(@cache.storage)
Corespunde codului PHP:
public function createService01(): Foo
{
$service = new Foo($this->getService('database'));
$service->setCacheStorage($this->getService('cache.storage'));
return $service;
}
Chiar și serviciile anonime pot fi referite folosind un callback, trebuie doar să specificați tipul lor (clasă sau interfață) în loc de numele lor. Cu toate acestea, acest lucru nu este de obicei necesar din cauza cablării automate.
services:
- create: Foo(@Nette\Database\Connection) # sau @\PDO
setup:
- setCacheStorage(@cache.storage)
Configurare
În secțiunea de configurare, enumerăm metodele care trebuie apelate la crearea serviciului:
services:
database:
create: PDO(%dsn%, %user%, %password%)
setup:
- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
Corespunde codului PHP:
public function createServiceDatabase(): PDO
{
$service = new PDO('...', '...', '...');
$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $service;
}
Proprietățile pot fi, de asemenea, setate. Adăugarea unui element la o matrice este, de asemenea, acceptată și trebuie scrisă între ghilimele pentru a nu intra în conflict cu sintaxa NEON:
services:
foo:
create: Foo
setup:
- $value = 123
- '$onClick[]' = [@bar, clickHandler]
Corespunde codului PHP:
public function createServiceFoo(): Foo
{
$service = new Foo;
$service->value = 123;
$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
return $service;
}
Cu toate acestea, metodele statice sau metodele altor servicii pot fi, de asemenea, apelate în configurare. Le transmitem
serviciul real ca @self
:
services:
foo:
create: Foo
setup:
- My\Helpers::initializeFoo(@self)
- @anotherService::setFoo(@self)
Corespunde codului PHP:
public function createServiceFoo(): Foo
{
$service = new Foo;
My\Helpers::initializeFoo($service);
$this->getService('anotherService')->setFoo($service);
return $service;
}
Cablare automată
Cheia autowired poate fi utilizată pentru a exclude un serviciu de la autowiring sau pentru a influența comportamentul acestuia. Pentru mai multe informații, consultați capitolul despre autowiring.
services:
foo:
create: Foo
autowired: false # foo este eliminat din autocablarea
Etichete
Informațiile despre utilizatori pot fi adăugate la serviciile individuale sub formă de etichete:
services:
foo:
create: Foo
tags:
- cached
Etichetele pot avea, de asemenea, o valoare:
services:
foo:
create: Foo
tags:
logger: monolog.logger.event
O matrice de servicii cu anumite etichete poate fi transmisă ca argument cu ajutorul funcției tagged()
. De
asemenea, se pot specifica mai multe etichete separate prin virgulă.
services:
- LoggersDependent( tagged(logger) )
Numele serviciilor pot fi obținute din containerul DI folosind metoda findByTag()
:
$names = $container->findByTag('logger');
// $names este o matrice care conține numele serviciului și valoarea etichetei.
// adică ['foo' => 'monolog.logger.event', ...]
Modul de injectare
Indicatorul inject: true
este utilizat pentru a activa trecerea dependențelor prin intermediul variabilelor
publice cu adnotarea inject
și metodele inject*().
services:
articles:
create: App\Model\Articles
inject: true
În mod implicit, inject
este activat numai pentru prezentatori.
Modificarea serviciilor
Există o serie de servicii în containerul DI care au fost adăugate prin încorporare sau prin extensia dumneavoastră. Definițiile acestor servicii pot fi modificate în configurație. De
exemplu, pentru serviciul application.application
, care este în mod implicit un obiect
Nette\Application\Application
, putem modifica clasa:
services:
application.application:
create: MyApplication
alteration: true
Steagul alteration
este informativ și spune că nu facem decât să modificăm un serviciu existent.
De asemenea, putem adăuga o configurare:
services:
application.application:
create: MyApplication
alteration: true
setup:
- '$onStartup[]' = [@resource, init]
Atunci când rescriem un serviciu, este posibil să dorim să eliminăm argumentele, elementele de configurare sau etichetele
inițiale, pentru aceasta existând reset
:
services:
application.application:
create: MyApplication
alteration: true
reset:
- arguments
- setup
- tags
Un serviciu adăugat prin extensie poate fi, de asemenea, eliminat din container:
services:
cache.journal: false