Definiowanie usług
Konfiguracja to miejsce, w którym umieszczamy nasze niestandardowe definicje usług. Służy do tego sekcja
services
.
Na przykład w ten sposób tworzymy serwis o nazwie database
, który będzie instancją klasy
PDO
:
services:
database: PDO('sqlite::memory:')
Nazewnictwo usług służy do odwoływania się do nich. Jeśli usługa nie jest przywoływana, nie musi być nazwana. Więc po prostu używamy wypunktowania zamiast nazwy:
services:
- PDO('sqlite::memory:') # anonimowa usługa
Wpis jednowierszowy może być rozbity na wiele wierszy, aby umożliwić dodanie innych klawiszy, takich jak konfiguracja. Alias dla klucza create:
to factory:
.
services:
database:
create: PDO('sqlite::memory:')
setup: ...
Usługa jest następnie pobierana z kontenera DI za pomocą metody getService()
by name lub lepiej
getByType()
by type:
$database = $container->getService('database');
$database = $container->getByType(PDO::class);
Tworzenie usługi
Najczęściej tworzymy usługę, tworząc po prostu instancję klasy:
services:
database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
Co generuje metodę fabryczną w kontenerze DI:
public function createServiceDatabase(): PDO
{
return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
}
Alternatywnie, klucz arguments
może być użyty do przekazania argumentów:
services:
database:
create: PDO
arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
Metoda statyczna może również tworzyć usługę:
services:
database: My\Database::create(root, secret)
Odpowiada kodowi PHP:
public function createServiceDatabase(): PDO
{
return My\Database::create('root', 'secret');
}
Zakłada się, że metoda statyczna My\Database::create()
ma zdefiniowaną wartość zwrotną, którą kontener DI
musi znać. Jeśli go nie ma, zapisz typ do konfiguracji:
services:
database:
create: My\Database::create(root, secret)
type: PDO
Nette DI daje nam niezwykle potężne środki wyrazu, które możesz wykorzystać do napisania niemal wszystkiego. Na
przykład, aby odwołać się do innej usługi i wywołać jej metodę. Dla uproszczenia,
zamiast ->
, używamy ::
services:
routerFactory: App\Router\Factory
router: @routerFactory::create()
Odpowiada kodowi PHP:
public function createServiceRouterFactory(): App\Router\Factory
{
return new App\Router\Factory;
}
public function createServiceRouter(): Router
{
return $this->getService('routerFactory')->create();
}
Wywołania metod mogą być łączone łańcuchowo, tak jak w PHP:
services:
foo: FooFactory::build()::get()
Odpowiada kodowi PHP:
public function createServiceFoo()
{
return FooFactory::build()->get();
}
Argumenty
Parametry nazwane mogą być również używane do przekazywania argumentów:
services:
database: PDO(
'mysql:host=127.0.0.1;dbname=test' # pozycja
username: root # nazwa
password: secret # nazwa
)
Przy dzieleniu argumentów na wiele linii, użycie przecinków jest opcjonalne.
Oczywiście jako argumenty mogą być użyte inne usługi lub parametry:
services:
- Foo(@anotherService, %appDir%)
Odpowiada kodowi PHP:
public function createService01(): Foo
{
return new Foo($this->getService('anotherService'), '...');
}
Jeśli pierwszy argument ma być autowpisywany, a chcemy
dołączyć drugi argument, to pomijamy pierwszy argument za pomocą _
, tedy např. Foo(_, %appDir%)
.
Albo jeszcze lepiej, po prostu przekaż drugi argument jako nazwany parametr, np. Foo(path: %appDir%)
.
Nette DI i format NEON dają nam niezwykle potężne zasoby ekspresyjne, które można wykorzystać do napisania niemal wszystkiego. Tak więc argumentem może być nowo utworzony obiekt, można wywoływać metody statyczne, metody innych serwisów, a nawet funkcje globalne przy użyciu specjalnej notacji:
services:
analyser: My\Analyser(
FilesystemIterator(%appDir%) # vytvoření objektu
DateTime::createFromFormat('Y-m-d') # volání statické metody
@anotherService # předání jiné služby
@http.request::getRemoteAddress() # volání metody jiné služby
::getenv(NetteMode) # volání globální funkce
)
Odpowiada on kodowi 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')
);
}
Funkcje specjalne
Możesz również użyć specjalnych funkcji w argumentach, aby zastąpić lub zanegować wartości:
not(%arg%)
negacjabool(%arg%)
lossless override to boolint(%arg%)
bezstratne przepisywanie na intfloat(%arg%)
bezstratny reflow do floatstring(%arg%)
bezstratne przepisywanie na ciąg znaków
services:
- Foo(
id: int(::getenv('ProjectId'))
productionMode: not(%debugMode%)
)
Bezstratne repartycjonowanie różni się od normalnego repartycjonowania PHP, np. przy użyciu (int)
, tym, że
rzuca wyjątek dla wartości nienumerycznych.
Jako argumenty można przekazać wiele usług. Tablicę wszystkich usług danego typu (tj. klasy lub interfejsu) tworzy funkcja
typed()
. Funkcja pomija usługi, które mają wyłączone autowiring, można podać wiele typów oddzielonych
przecinkami.
services:
- BarsDependent( typed(Bar) )
Możesz również przekazać tablicę usług automatycznie za pomocą autowiring.
Funkcja tagged()
tworzy tablicę wszystkich usług z określonym tagiem. Można również
podać wiele tagów oddzielonych przecinkiem.
services:
- LoggersDependent( tagged(logger) )
Usługi odsyłania
Do usług odwołujemy się za pomocą nazwy usługi i nazwy serwisu, więc na przykład @database
:
services:
- create: Foo(@database)
setup:
- setCacheStorage(@cache.storage)
Odpowiada kodowi PHP:
public function createService01(): Foo
{
$service = new Foo($this->getService('database'));
$service->setCacheStorage($this->getService('cache.storage'));
return $service;
}
Nawet anonimowe usługi mogą być przywoływane poprzez alias, wystarczy podać typ (klasa lub interfejs) zamiast nazwy. Zwykle jednak nie jest to konieczne ze względu na autowiring.
services:
- create: Foo(@Nette\Database\Connection) # nebo třeba @PDO.
setup:
- setCacheStorage(@cache.storage)
Ustawienie
W sekcji setup znajduje się lista metod, które należy wywołać podczas tworzenia usługi:
services:
database:
create: PDO(%dsn%, %user%, %password%)
setup:
- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
Odpowiada kodowi PHP:
public function createServiceDatabase(): PDO
{
$service = new PDO('...', '...', '...');
$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $service;
}
Można również ustawić wartości zmienne. Dodawanie elementu do tablicy jest również obsługiwane, ale musi być napisane w cudzysłowie, aby uniknąć konfliktu ze składnią NEON:
services:
foo:
create: Foo
setup:
- $value = 123
- '$onClick[]' = [@bar, clickHandler]
Odpowiada kodowi PHP:
public function createServiceFoo(): Foo
{
$service = new Foo;
$service->value = 123;
$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
return $service;
}
Jednak metody statyczne lub metody innych usług mogą być wywoływane w konfiguracji. Rzeczywista usługa jest przekazywana
do nich jako @self
:
services:
foo:
create: Foo
setup:
- My\Helpers::initializeFoo(@self)
- @anotherService::setFoo(@self)
Odpowiada kodowi PHP:
public function createServiceFoo(): Foo
{
$service = new Foo;
My\Helpers::initializeFoo($service);
$this->getService('anotherService')->setFoo($service);
return $service;
}
Autowiring
Możesz użyć klucza autowired, aby wykluczyć usługę z autowiring lub wpłynąć na jej zachowanie. Więcej informacji można znaleźć w rozdziale dotyczącym autowiring.
services:
foo:
create: Foo
autowired: false # service foo jest wyłączony z autowiring
Tagi
Informacje o użytkownikach mogą być dodawane do poszczególnych serwisów w postaci tagów:
services:
foo:
create: Foo
tags:
- cached
Tagi mogą mieć również wartość:
services:
foo:
create: Foo
tags:
logger: monolog.logger.event
Możesz przekazać tablicę usług z określonymi tagami jako argument za pomocą funkcji tagged()
. Możesz
określić wiele tagów oddzielonych przecinkami.
services:
- LoggersDependent( tagged(logger) )
Nazwy usług można pobrać z kontenera DI za pomocą metody findByTag()
:
$names = $container->findByTag('logger');
// $names jest tablicą zawierającą nazwę serwisu i wartość tagu
// np. ['foo' => 'monolog.logger.event', ...]
Tryb wtrysku
Flaga inject: true
służy do aktywowania przekazywania zależności poprzez zmienne publiczne z adnotacją inject i metodami inject*().
services:
articles:
create: App\Model\Articles
inject: true
Domyślnie strona inject
jest aktywowana tylko dla prezenterów.
Modyfikacja usług
Istnieje wiele usług w kontenerze DI, które dodały wbudowane lub twoje rozszerzenia. Definicje
tych usług mogą być modyfikowane w konfiguracji. Na przykład dla serwisu application.application
, który
domyślnie jest obiektem Nette\Application\Application
, możemy zmienić klasę:
services:
application.application:
create: MyApplication
alteration: true
Flaga alteration
ma charakter informacyjny i mówi, że właśnie modyfikujemy istniejącą usługę.
Możemy również dodać ustawienie:
services:
application.application:
create: MyApplication
alteration: true
setup:
- '$onStartup[]' = [@resource, init]
Podczas przepisywania usługi możemy chcieć usunąć oryginalne argumenty, elementy ustawień lub tagi, do czego służy
reset
:
services:
application.application:
create: MyApplication
alteration: true
reset:
- arguments
- setup
- tags
Usługa dodana przez rozszerzenie może być również usunięta z kontenera:
services:
cache.journal: false