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%) negarea
  • bool(%arg%) cast fără pierderi în bool
  • int(%arg%) lossless cast to int
  • float(%arg%) lossless cast to float
  • string(%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
versiune: 3.x