Définitions des services

La configuration est l'endroit où nous plaçons les définitions des services personnalisés. Ceci est fait dans la section services.

Par exemple, voici comment nous créons un service nommé database, qui sera une instance de la classe PDO:

services:
	database: PDO('sqlite::memory:')

Le nommage des services est utilisé pour nous permettre de les référencer. Si un service n'est pas référencé, il n'est pas nécessaire de le nommer. Nous utilisons donc simplement une puce au lieu d'un nom :

services:
	- PDO('sqlite::memory:') # service anonyme

Une entrée d'une ligne peut être décomposée en plusieurs lignes pour permettre l'ajout de clés supplémentaires, telles que setup. L'alias de la clé create: est factory:.

services:
	database:
		create: PDO('sqlite::memory:')
		setup: ...

Nous récupérons ensuite le service dans le conteneur DI en utilisant la méthode getService() par nom, ou mieux encore, la méthode getByType() par type :

$database = $container->getService('database');
$database = $container->getByType(PDO::class);

Création d'un service

Le plus souvent, nous créons un service en créant simplement une instance d'une classe :

services:
	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)

Ce qui va générer une méthode de fabrique dans le conteneur DI:

public function createServiceDatabase(): PDO
{
	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
}

Alternativement, une clé arguments peut être utilisée pour passer des arguments:

services:
	database:
		create: PDO
		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]

Une méthode statique peut également créer un service :

services:
	database: My\Database::create(root, secret)

Correspond au code PHP :

public function createServiceDatabase(): PDO
{
	return My\Database::create('root', 'secret');
}

Une méthode statique My\Database::create() est supposée avoir une valeur de retour définie que le conteneur DI doit connaître. S'il ne l'a pas, nous écrivons le type dans la configuration :

services:
	database:
		create: My\Database::create(root, secret)
		type: PDO

Nette DI vous donne des facilités d'expression extrêmement puissantes pour écrire presque n'importe quoi. Par exemple, pour faire référence à un autre service et appeler sa méthode. Pour simplifier, on utilise :: au lieu de ->.

services:
	routerFactory: App\Router\Factory
	router: @routerFactory::create()

Correspond au code PHP :

public function createServiceRouterFactory(): App\Router\Factory
{
	return new App\Router\Factory;
}

public function createServiceRouter(): Router
{
	return $this->getService('routerFactory')->create();
}

Les appels de méthode peuvent être enchaînés comme en PHP :

services:
	foo: FooFactory::build()::get()

Correspond au code PHP :

public function createServiceFoo()
{
	return FooFactory::build()->get();
}

Arguments

Les paramètres nommés peuvent également être utilisés pour transmettre des arguments :

services:
	database: PDO(
		mysql:host=127.0.0.1;dbname=test' # positionnel
		username: root                    # nommé
		password: secret                  # nommé
	)

L'utilisation de virgules est facultative lorsque les arguments sont répartis sur plusieurs lignes.

Bien entendu, nous pouvons également utiliser d'autres services ou paramètres comme arguments :

services:
	- Foo(@anotherService, %appDir%)

Correspond au code PHP :

public function createService01(): Foo
{
	return new Foo($this->getService('anotherService'), '...');
}

Si le premier argument est autodirigé et que vous souhaitez spécifier le second, omettez le premier avec _ character, for example Foo(_, %appDir%). Ou mieux encore, passez uniquement le second argument comme paramètre nommé, par exemple Foo(path: %appDir%).

Nette DI et le format NEON vous offrent des possibilités d'expression extrêmement puissantes pour écrire presque tout. Ainsi, un argument peut être un objet nouvellement créé, vous pouvez appeler des méthodes statiques, des méthodes d'autres services, ou même des fonctions globales en utilisant une notation spéciale :

services:
	analyser: My\Analyser(
		FilesystemIterator(%appDir%)        # créer un objet
		DateTime::createFromFormat('Y-m-d') # appelle la méthode statique
		@anotherService                     # passage d'un autre service
		@http.request::getRemoteAddress()   # appel d'une autre méthode de service
		::getenv(NetteMode)                 # appel d'une fonction globale
	)

Correspond au code 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')
	);
}

Fonctions spéciales

Vous pouvez également utiliser des fonctions spéciales dans les arguments pour exprimer ou nier des valeurs :

  • not(%arg%) négation
  • bool(%arg%) Conversion sans perte en bool
  • int(%arg%) Conversion sans perte en int
  • float(%arg%) conversion sans perte en float
  • string(%arg%) Moulage sans perte vers string
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)

La réécriture sans perte diffère de la réécriture PHP normale, par exemple en utilisant (int), car elle lève une exception pour les valeurs non numériques.

Plusieurs services peuvent être passés en argument. Un tableau de tous les services d'un type particulier (c'est-à-dire une classe ou une interface) est créé par la fonction typed(). La fonction omettra les services dont le câblage automatique est désactivé, et plusieurs types séparés par une virgule peuvent être spécifiés.

services:
	- BarsDependent( typed(Bar) )

Vous pouvez également passer un tableau de services automatiquement en utilisant le câblage automatique.

Un tableau de tous les services avec une certaine étiquette est créé par la fonction tagged(). Plusieurs balises séparées par une virgule peuvent être spécifiées.

services:
	- LoggersDependent( tagged(logger) )

Services de référencement

Les services individuels sont référencés à l'aide du caractère @ and name, so for example @database:

services:
	- create: Foo(@database)
	  setup:
			- setCacheStorage(@cache.storage)

Correspond au code PHP :

public function createService01(): Foo
{
	$service = new Foo($this->getService('database'));
	$service->setCacheStorage($this->getService('cache.storage'));
	return $service;
}

Même les services anonymes peuvent être référencés à l'aide d'un callback, il suffit de spécifier leur type (classe ou interface) au lieu de leur nom. Cependant, cela n'est généralement pas nécessaire en raison du câblage automatique.

services:
	- create: Foo(@Nette\Database\Connection)  # ou @\PDO
	  setup:
			- setCacheStorage(@cache.storage)

Configuration

Dans la section “setup”, nous listons les méthodes à appeler lors de la création du service :

services:
	database:
		create: PDO(%dsn%, %user%, %password%)
		setup:
			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)

Correspond au code PHP :

public function createServiceDatabase(): PDO
{
	$service = new PDO('...', '...', '...');
	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	return $service;
}

Les propriétés peuvent également être définies. L'ajout d'un élément à un tableau est également supporté, et doit être écrit entre guillemets pour ne pas entrer en conflit avec la syntaxe NEON :

services:
	foo:
		create: Foo
		setup:
			- $value = 123
			- '$onClick[]' = [@bar, clickHandler]

Correspond au code PHP :

public function createServiceFoo(): Foo
{
	$service = new Foo;
	$service->value = 123;
	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
	return $service;
}

Cependant, les méthodes statiques ou les méthodes d'autres services peuvent également être appelées dans la configuration. Nous leur passons le service réel en tant que @self:

services:
	foo:
		create: Foo
		setup:
			- My\Helpers::initializeFoo(@self)
			- @anotherService::setFoo(@self)

Correspond au code PHP :

public function createServiceFoo(): Foo
{
	$service = new Foo;
	My\Helpers::initializeFoo($service);
	$this->getService('anotherService')->setFoo($service);
	return $service;
}

Câblage automatique

La clé autowired peut être utilisée pour exclure un service de l'autowiring ou pour influencer son comportement. Voir le chapitre sur le câblage automatique pour plus d'informations.

services:
	foo:
		create: Foo
		autowired: false # foo est retiré de l'autowiring

Tags

Des informations sur les utilisateurs peuvent être ajoutées aux services individuels sous la forme de balises :

services:
	foo:
		create: Foo
		tags:
			- cached

Les étiquettes peuvent également avoir une valeur :

services:
	foo:
		create: Foo
		tags:
			logger: monolog.logger.event

Un tableau de services avec certaines balises peut être passé comme argument en utilisant la fonction tagged(). Plusieurs balises séparées par une virgule peuvent également être spécifiées.

services:
	- LoggersDependent( tagged(logger) )

Les noms des services peuvent être obtenus du conteneur DI à l'aide de la méthode findByTag():

$names = $container->findByTag('logger');
// $names est un tableau contenant le nom du service et la valeur du tag
// c'est-à-dire ['foo' => 'monolog.logger.event', ...]

Mode d'injection

L'indicateur inject: true est utilisé pour activer le passage des dépendances via des variables publiques avec l'annotation inject et les méthodes inject*().

services:
	articles:
		create: App\Model\Articles
		inject: true

Par défaut, inject n'est activé que pour les présentateurs.

Modification des services

Il existe un certain nombre de services dans le conteneur DI qui ont été ajoutés par l'intégration ou votre extension. Les définitions de ces services peuvent être modifiées dans la configuration. Par exemple, pour le service application.application, qui est par défaut un objet Nette\Application\Application, nous pouvons changer la classe :

services:
	application.application:
		create: MyApplication
		alteration: true

Le drapeau alteration est informatif et indique que nous ne faisons que modifier un service existant.

Nous pouvons également ajouter un service :

services:
	application.application:
		create: MyApplication
		alteration: true
		setup:
			- '$onStartup[]' = [@resource, init]

Lorsque nous réécrivons un service, nous pouvons vouloir supprimer les arguments, les éléments de configuration ou les balises d'origine, ce à quoi sert reset:

services:
	application.application:
		create: MyApplication
		alteration: true
		reset:
			- arguments
			- setup
			- tags

Un service ajouté par extension peut également être retiré du conteneur :

services:
	cache.journal: false
version: 3.x