Nette Documentation Preview

syntax
Definiowanie usług
******************

.[perex]
Konfiguracja to miejsce, w którym instruujemy kontener DI, jak składać poszczególne usługi i jak łączyć je z innymi zależnościami. Nette zapewnia bardzo przejrzysty i elegancki sposób na osiągnięcie tego celu.

Sekcja `services` w pliku konfiguracyjnym NEON to miejsce, w którym definiujemy nasze niestandardowe usługi i ich konfiguracje. Przyjrzyjmy się prostemu przykładowi definiowania usługi o nazwie `database`, która reprezentuje instancję klasy `PDO`:

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

Ta konfiguracja skutkuje następującą metodą fabryczną w [kontenerze DI |container]:

```php
public function createServiceDatabase(): PDO
{
	return new PDO('sqlite::memory:');
}
```

Nazwy usług pozwalają nam odwoływać się do nich w innych częściach pliku konfiguracyjnego, używając formatu `@serviceName`. Jeśli nie ma potrzeby nazywania usługi, możemy po prostu użyć punktora:

```neon
services:
	- PDO('sqlite::memory:')
```

Aby pobrać usługę z kontenera DI, możemy użyć metody `getService()` z nazwą usługi jako parametrem lub metody `getByType()` z typem usługi:

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


Tworzenie usług .[#toc-service-creation]
========================================

Najczęściej tworzymy usługę po prostu poprzez instancjonowanie określonej klasy. Na przykład:

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

Jeśli musimy rozszerzyć konfigurację o dodatkowe klucze, definicję można rozszerzyć na wiele linii:

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

Klucz `create` ma alias `factory`, obie wersje są powszechne w praktyce. Zalecamy jednak używanie `create`.

Argumenty konstruktora lub metoda tworzenia mogą być alternatywnie zapisane w kluczu `arguments`:

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

Usługi nie muszą być tworzone tylko przez prostą instancję klasy; mogą one również wynikać z wywoływania metod statycznych lub metod innych usług:

```neon
services:
	database: DatabaseFactory::create()
	router: @routerFactory::create()
```

Zauważ, że dla uproszczenia, zamiast `->`, używamy `::`, patrz [wyrażenie oznacza |#expression means]. Te metody fabryczne są generowane:

```php
public function createServiceDatabase(): PDO
{
	return DatabaseFactory::create();
}

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

Kontener DI musi znać typ tworzonej usługi. Jeśli tworzymy usługę przy użyciu metody, która nie ma określonego typu zwracanego, musimy wyraźnie wspomnieć o tym typie w konfiguracji:

```neon
services:
	database:
		create: DatabaseFactory::create()
		type: PDO
```


Argumenty .[#toc-arguments]
===========================

Przekazujemy argumenty do konstruktorów i metod w sposób bardzo podobny do zwykłego PHP:

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

Dla lepszej czytelności możemy wypisać argumenty w osobnych wierszach. W tym formacie użycie przecinków jest opcjonalne:

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

Można również nazwać argumenty, co pozwala nie martwić się o ich kolejność:

```neon
services:
	database: PDO(
		username: root
		password: secret
		dsn: 'mysql:host=127.0.0.1;dbname=test'
	)
```

Jeśli chcesz pominąć niektóre argumenty i użyć ich wartości domyślnych lub wstawić usługę poprzez [autowiring |autowiring], użyj podkreślenia:

```neon
services:
	foo: Foo(_, %appDir%)
```

Argumentami mogą być usługi, parametry i wiele innych, patrz [środki wyrazu |#expression means].


Konfiguracja .[#toc-setup]
==========================

W sekcji `setup` definiujemy metody, które powinny być wywoływane podczas tworzenia usługi.

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

W PHP wyglądałoby to następująco:

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

Oprócz wywoływania metod, można również przekazywać wartości do właściwości. Dodawanie elementu do tablicy jest również obsługiwane, ale należy je ująć w cudzysłów, aby uniknąć kolizji ze składnią NEON:

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

W PHP tłumaczyłoby się to na:

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

W konfiguracji można również wywoływać metody statyczne lub metody innych usług. Jeśli chcesz przekazać bieżącą usługę jako argument, użyj `@self`:

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

Zauważ, że dla uproszczenia, zamiast `->`, używamy `::`, patrz [środki wyrazu |#expression means]. Spowoduje to wygenerowanie następującej metody fabrycznej:

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


Środki wyrazu .[#toc-expression-means]
======================================

Nette DI zapewnia nam wyjątkowo bogate możliwości wyrażania, pozwalając nam wyrazić prawie wszystko. W plikach konfiguracyjnych możemy używać [parametrów |configuration#parameters]:

```neon
# parametr
%wwwDir%

# wartość pod kluczem parametru
%mailer.user%

# parametr w ciągu znaków
'%wwwDir%/images'
```

Możemy również tworzyć obiekty, wywoływać metody i funkcje:

```neon
# utworzyć obiekt
DateTime()

# wywołać metodę statyczną
Collator::create(%locale%)

# wywołać funkcję PHP
::getenv(DB_USER)
```

Odnosić się do usług poprzez ich nazwę lub typ:

```neon
# usługa według nazwy
@database

# usługa według typu
@Nette\Database\Connection
```

Używaj składni wywoływalnej pierwszej klasy: .{data-version:3.2.0}

```neon
# creating a callback, equivalent to [@user, logout]
@user::logout(...)
```

Użyj stałych:

```neon
# stała klasy
FilesystemIterator::SKIP_DOTS

# stała globalna uzyskana przez funkcję PHP constant()
::constant(PHP_VERSION)
```

Wywołania metod mogą być łańcuchowane, tak jak w PHP. Dla uproszczenia, zamiast `->`, używamy `::`:

```neon
DateTime()::format('Y-m-d')
# PHP: (new DateTime())->format('Y-m-d')

@http.request::getUrl()::getHost()
# PHP: $this->getService('http.request')->getUrl()->getHost()
```

Wyrażenia te mogą być używane w dowolnym miejscu podczas [tworzenia usług |#Service Creation], w [argumentach |#Arguments], w sekcji [konfiguracji |#setup] lub w [parametrach |configuration#parameters]:

```neon
parameters:
	ipAddress: @http.request::getRemoteAddress()

services:
	database:
		create: DatabaseFactory::create( @anotherService::getDsn() )
		setup:
			- initialize( ::getenv('DB_USER') )
```


Funkcje specjalne .[#toc-special-functions]
-------------------------------------------

W plikach konfiguracyjnych można korzystać z tych funkcji specjalnych:

- `not()` dla negacji wartości
- `bool()`, `int()`, `float()`, `string()` do bezstratnego rzutowania typów
- `typed()` do generowania tablicy wszystkich usług określonego typu
- `tagged()` do tworzenia tablicy wszystkich usług z danym tagiem

```neon
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)
```

W porównaniu do konwencjonalnego rzutowania typów w PHP, takiego jak `(int)`, bezstratne rzutowanie typów rzuci wyjątek dla wartości nienumerycznych.

Funkcja `typed()` tworzy tablicę wszystkich usług określonego typu (klasy lub interfejsu). Wyklucza ona usługi z wyłączonym autowiringiem. Można określić wiele typów, oddzielając je przecinkami.

```neon
services:
	- BarsDependent( typed(Bar) )
```

Można również automatycznie przekazać tablicę usług określonego typu jako argument przy użyciu [autowiring |autowiring#Collection of Services].

Funkcja `tagged()` tworzy tablicę wszystkich usług z określonym tagiem. Można wymienić wiele tagów, oddzielając je przecinkami.

```neon
services:
	- LoggersDependent( tagged(logger) )
```


Okablowanie .[#toc-autowiring]
==============================

Klucz `autowired` pozwala modyfikować zachowanie autoprzewodowania dla określonej usługi. Więcej szczegółów można znaleźć [w |autowiring] rozdziale autowiring.

```neon
services:
	foo:
		create: Foo
		autowired: false     # usługa foo jest wyłączona z automatycznego okablowania
```


Tagi .[#toc-tags]
=================

Tagi służą do dodawania dodatkowych informacji do usług. Do usługi można przypisać jeden lub więcej tagów:

```neon
services:
	foo:
		create: Foo
		tags:
			- cached
```

Tagi mogą również zawierać wartości:

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

Aby pobrać wszystkie usługi z określonymi tagami, można użyć funkcji `tagged()`:

```neon
services:
	- LoggersDependent( tagged(logger) )
```

W kontenerze DI można uzyskać nazwy wszystkich usług z określonym tagiem za pomocą metody `findByTag()`:

```php
$names = $container->findByTag('logger');
// $names to tablica zawierająca nazwę usługi i wartość tagu
// np. ['foo' => 'monolog.logger.event', ...].
```


Tryb wstrzykiwania .[#toc-inject-mode]
======================================

Użycie flagi `inject: true` aktywuje przekazywanie zależności poprzez zmienne publiczne z adnotacją [inject |best-practices:inject-method-attribute#Inject Attributes] i metodami [inject*() |best-practices:inject-method-attribute#inject Methods].

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

Domyślnie flaga `inject` jest aktywowana tylko dla prezenterów.


Modyfikacje usługi .[#toc-service-modifications]
================================================

Kontener DI zawiera wiele usług dodanych przez [rozszerzenia |#extensions] wbudowane lub [użytkownika |#extensions]. Definicje tych usług można modyfikować bezpośrednio w konfiguracji. Na przykład można zmienić klasę usługi `application.application`, która jest konwencjonalnie `Nette\Application\Application`, na coś innego:

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

Flaga `alteration` ma charakter informacyjny, wskazując, że jedynie modyfikujemy istniejącą usługę.

Możemy również uzupełnić konfigurację:

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

Podczas nadpisywania usługi może być konieczne usunięcie oryginalnych argumentów, elementów konfiguracji lub tagów, co jest przydatne w przypadku `reset`:

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

Jeśli chcesz usunąć usługę dodaną przez rozszerzenie, możesz to zrobić w następujący sposób:

```neon
services:
	cache.journal: false
```

Definiowanie usług

Konfiguracja to miejsce, w którym instruujemy kontener DI, jak składać poszczególne usługi i jak łączyć je z innymi zależnościami. Nette zapewnia bardzo przejrzysty i elegancki sposób na osiągnięcie tego celu.

Sekcja services w pliku konfiguracyjnym NEON to miejsce, w którym definiujemy nasze niestandardowe usługi i ich konfiguracje. Przyjrzyjmy się prostemu przykładowi definiowania usługi o nazwie database, która reprezentuje instancję klasy PDO:

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

Ta konfiguracja skutkuje następującą metodą fabryczną w kontenerze DI:

public function createServiceDatabase(): PDO
{
	return new PDO('sqlite::memory:');
}

Nazwy usług pozwalają nam odwoływać się do nich w innych częściach pliku konfiguracyjnego, używając formatu @serviceName. Jeśli nie ma potrzeby nazywania usługi, możemy po prostu użyć punktora:

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

Aby pobrać usługę z kontenera DI, możemy użyć metody getService() z nazwą usługi jako parametrem lub metody getByType() z typem usługi:

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

Tworzenie usług

Najczęściej tworzymy usługę po prostu poprzez instancjonowanie określonej klasy. Na przykład:

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

Jeśli musimy rozszerzyć konfigurację o dodatkowe klucze, definicję można rozszerzyć na wiele linii:

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

Klucz create ma alias factory, obie wersje są powszechne w praktyce. Zalecamy jednak używanie create.

Argumenty konstruktora lub metoda tworzenia mogą być alternatywnie zapisane w kluczu arguments:

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

Usługi nie muszą być tworzone tylko przez prostą instancję klasy; mogą one również wynikać z wywoływania metod statycznych lub metod innych usług:

services:
	database: DatabaseFactory::create()
	router: @routerFactory::create()

Zauważ, że dla uproszczenia, zamiast ->, używamy ::, patrz wyrażenie oznacza. Te metody fabryczne są generowane:

public function createServiceDatabase(): PDO
{
	return DatabaseFactory::create();
}

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

Kontener DI musi znać typ tworzonej usługi. Jeśli tworzymy usługę przy użyciu metody, która nie ma określonego typu zwracanego, musimy wyraźnie wspomnieć o tym typie w konfiguracji:

services:
	database:
		create: DatabaseFactory::create()
		type: PDO

Argumenty

Przekazujemy argumenty do konstruktorów i metod w sposób bardzo podobny do zwykłego PHP:

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

Dla lepszej czytelności możemy wypisać argumenty w osobnych wierszach. W tym formacie użycie przecinków jest opcjonalne:

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

Można również nazwać argumenty, co pozwala nie martwić się o ich kolejność:

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

Jeśli chcesz pominąć niektóre argumenty i użyć ich wartości domyślnych lub wstawić usługę poprzez autowiring, użyj podkreślenia:

services:
	foo: Foo(_, %appDir%)

Argumentami mogą być usługi, parametry i wiele innych, patrz środki wyrazu.

Konfiguracja

W sekcji setup definiujemy metody, które powinny być wywoływane podczas tworzenia usługi.

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

W PHP wyglądałoby to następująco:

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

Oprócz wywoływania metod, można również przekazywać wartości do właściwości. Dodawanie elementu do tablicy jest również obsługiwane, ale należy je ująć w cudzysłów, aby uniknąć kolizji ze składnią NEON:

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

W PHP tłumaczyłoby się to na:

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

W konfiguracji można również wywoływać metody statyczne lub metody innych usług. Jeśli chcesz przekazać bieżącą usługę jako argument, użyj @self:

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

Zauważ, że dla uproszczenia, zamiast ->, używamy ::, patrz środki wyrazu. Spowoduje to wygenerowanie następującej metody fabrycznej:

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

Środki wyrazu

Nette DI zapewnia nam wyjątkowo bogate możliwości wyrażania, pozwalając nam wyrazić prawie wszystko. W plikach konfiguracyjnych możemy używać parametrów:

# parametr
%wwwDir%

# wartość pod kluczem parametru
%mailer.user%

# parametr w ciągu znaków
'%wwwDir%/images'

Możemy również tworzyć obiekty, wywoływać metody i funkcje:

# utworzyć obiekt
DateTime()

# wywołać metodę statyczną
Collator::create(%locale%)

# wywołać funkcję PHP
::getenv(DB_USER)

Odnosić się do usług poprzez ich nazwę lub typ:

# usługa według nazwy
@database

# usługa według typu
@Nette\Database\Connection

Używaj składni wywoływalnej pierwszej klasy:

# creating a callback, equivalent to [@user, logout]
@user::logout(...)

Użyj stałych:

# stała klasy
FilesystemIterator::SKIP_DOTS

# stała globalna uzyskana przez funkcję PHP constant()
::constant(PHP_VERSION)

Wywołania metod mogą być łańcuchowane, tak jak w PHP. Dla uproszczenia, zamiast ->, używamy :::

DateTime()::format('Y-m-d')
# PHP: (new DateTime())->format('Y-m-d')

@http.request::getUrl()::getHost()
# PHP: $this->getService('http.request')->getUrl()->getHost()

Wyrażenia te mogą być używane w dowolnym miejscu podczas tworzenia usług, w argumentach, w sekcji konfiguracji lub w parametrach:

parameters:
	ipAddress: @http.request::getRemoteAddress()

services:
	database:
		create: DatabaseFactory::create( @anotherService::getDsn() )
		setup:
			- initialize( ::getenv('DB_USER') )

Funkcje specjalne

W plikach konfiguracyjnych można korzystać z tych funkcji specjalnych:

  • not() dla negacji wartości
  • bool(), int(), float(), string() do bezstratnego rzutowania typów
  • typed() do generowania tablicy wszystkich usług określonego typu
  • tagged() do tworzenia tablicy wszystkich usług z danym tagiem
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)

W porównaniu do konwencjonalnego rzutowania typów w PHP, takiego jak (int), bezstratne rzutowanie typów rzuci wyjątek dla wartości nienumerycznych.

Funkcja typed() tworzy tablicę wszystkich usług określonego typu (klasy lub interfejsu). Wyklucza ona usługi z wyłączonym autowiringiem. Można określić wiele typów, oddzielając je przecinkami.

services:
	- BarsDependent( typed(Bar) )

Można również automatycznie przekazać tablicę usług określonego typu jako argument przy użyciu autowiring.

Funkcja tagged() tworzy tablicę wszystkich usług z określonym tagiem. Można wymienić wiele tagów, oddzielając je przecinkami.

services:
	- LoggersDependent( tagged(logger) )

Okablowanie

Klucz autowired pozwala modyfikować zachowanie autoprzewodowania dla określonej usługi. Więcej szczegółów można znaleźć w rozdziale autowiring.

services:
	foo:
		create: Foo
		autowired: false     # usługa foo jest wyłączona z automatycznego okablowania

Tagi

Tagi służą do dodawania dodatkowych informacji do usług. Do usługi można przypisać jeden lub więcej tagów:

services:
	foo:
		create: Foo
		tags:
			- cached

Tagi mogą również zawierać wartości:

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

Aby pobrać wszystkie usługi z określonymi tagami, można użyć funkcji tagged():

services:
	- LoggersDependent( tagged(logger) )

W kontenerze DI można uzyskać nazwy wszystkich usług z określonym tagiem za pomocą metody findByTag():

$names = $container->findByTag('logger');
// $names to tablica zawierająca nazwę usługi i wartość tagu
// np. ['foo' => 'monolog.logger.event', ...].

Tryb wstrzykiwania

Użycie flagi inject: true aktywuje przekazywanie zależności poprzez zmienne publiczne z adnotacją inject i metodami inject*().

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

Domyślnie flaga inject jest aktywowana tylko dla prezenterów.

Modyfikacje usługi

Kontener DI zawiera wiele usług dodanych przez rozszerzenia wbudowane lub użytkownika. Definicje tych usług można modyfikować bezpośrednio w konfiguracji. Na przykład można zmienić klasę usługi application.application, która jest konwencjonalnie Nette\Application\Application, na coś innego:

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

Flaga alteration ma charakter informacyjny, wskazując, że jedynie modyfikujemy istniejącą usługę.

Możemy również uzupełnić konfigurację:

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

Podczas nadpisywania usługi może być konieczne usunięcie oryginalnych argumentów, elementów konfiguracji lub tagów, co jest przydatne w przypadku reset:

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

Jeśli chcesz usunąć usługę dodaną przez rozszerzenie, możesz to zrobić w następujący sposób:

services:
	cache.journal: false