Konfiguracja kontenera DI
Przegląd opcji konfiguracyjnych kontenera Nette DI.
Plik konfiguracyjny
Kontenerem Nette DI łatwo steruje się za pomocą plików konfiguracyjnych. Zapisywane są one zwykle w formacie NEON. Zalecamy używanie edytorów z jego obsługą.
decorator: Dekorator
di: Kontener DI
extensions: Instalacja dodatkowych rozszerzeń DI
includes: Dołączanie plików
parameters: Parametry
search: Automatyczna rejestracja usług
services: Usługi
Aby zapisać string zawierający znak %, musisz go zescapować, podwajając na %%.
Parametry
W konfiguracji możesz zdefiniować parametry, których można potem używać jako części definicji usług. Pozwala to uczynić konfigurację czytelniejszą albo scentralizować wartości, które mogą się zmieniać.
parameters:
dsn: 'mysql:host=127.0.0.1;dbname=test'
user: root
password: secret
Do parametru dsn odwołujemy się w dowolnym miejscu konfiguracji zapisem %dsn%. Parametrów można
używać również wewnątrz stringów, jak '%wwwDir%/images'.
Parametry nie muszą być tylko stringami czy liczbami, mogą zawierać również tablice:
parameters:
mailer:
host: smtp.example.com
secure: ssl
user: franta@gmail.com
languages: [cs, en, de]
Do konkretnego klucza odwołujemy się jako %mailer.user%.
Jeśli Twój kod (np. klasa) potrzebuje wartości parametru, przekaż mu ją. Na przykład w konstruktorze. Nie istnieje globalny obiekt konfiguracji, którego klasy mogłyby pytać o wartości parametrów. Byłoby to złamanie zasady wstrzykiwania zależności.
Usługi
Zobacz osobny rozdział.
Dekorator
Jak zmodyfikować naraz wiele usług określonego typu? Na przykład jak wywołać konkretną metodę na wszystkich presenterach dziedziczących po określonej klasie bazowej? Od tego jest dekorator.
decorator:
# dla wszystkich usług będących instancjami tej klasy albo interfejsu
App\Presentation\BasePresenter:
setup:
- setProjectId(10) # wywołaj tę metodę
- $absoluteUrls = true # i ustaw zmienną
Dekoratora można też używać do ustawiania tagów albo włączania trybu inject.
decorator:
InjectableInterface:
tags: [mytag: 1]
inject: true
DI
Ustawienia techniczne kontenera DI.
di:
# pokazywać DIC w pasku Tracy?
debugger: ... # (bool) domyślnie autodetekcja (włączone, gdy Tracy jest obecne)
# typy parametrów, których nigdy nie autowirujesz
excluded: ... # (string[])
# włączyć leniwe tworzenie usług?
lazy: ... # (bool) domyślnie false
# klasa, po której dziedziczy kontener DI
parentClass: ... # (string) domyślnie Nette\DI\Container
Usługi leniwe
Ustawienie lazy: true aktywuje leniwe (odroczone) tworzenie usług. Oznacza to, że usługi nie są faktycznie
tworzone w chwili, gdy prosisz o nie kontener DI, lecz dopiero przy ich pierwszym użyciu. Może to przyspieszyć start aplikacji
i zmniejszyć zużycie pamięci, bo tworzone są tylko usługi faktycznie potrzebne dla danego żądania.
Dla konkretnej usługi leniwe tworzenie można dostosować.
Obiektów leniwych można używać tylko dla klas zdefiniowanych przez użytkownika, nie dla wewnętrznych klas PHP. Wymaga PHP 8.4 lub nowszego.
Eksport metadanych
Klasa kontenera DI zawiera również sporo metadanych. Możesz zmniejszyć jej rozmiar, ograniczając eksport metadanych.
di:
export:
# eksportować parametry?
parameters: false # (bool) domyślnie true
# eksportować tagi i które?
tags: # (string[]|bool) domyślnie wszystkie
- event.subscriber
# eksportować dane do autowiringu i które?
types: # (string[]|bool) domyślnie wszystkie
- Nette\Database\Connection
- Symfony\Component\Console\Application
Jeśli nie używasz $container->getParameters(), możesz wyłączyć eksport parametrów. Ponadto możesz
eksportować tylko te tagi, których faktycznie używasz do pobierania usług przez $container->findByTag(...).
Jeśli w ogóle nie wywołujesz tej metody, możesz całkowicie wyłączyć eksport tagów przez false.
Możesz znacząco ograniczyć metadane dla autowiringu,
wymieniając tylko te klasy, o które faktycznie prosisz przez $container->getByType(). Znów: jeśli nie
wywołujesz tej metody (albo wywołujesz ją tylko w pliku bootstrap, np. aby uzyskać
Nette\Application\Application), możesz całkowicie wyłączyć eksport typów przez false.
Rozszerzenia
Rejestracja dodatkowych rozszerzeń DI. Tak dodasz na przykład rozszerzenie DI Dibi\Bridges\Nette\DibiExtension3
pod nazwą dibi:
extensions:
dibi: Dibi\Bridges\Nette\DibiExtension3
Konfigurujesz je potem w sekcji dibi:
dibi:
host: localhost
Jako rozszerzenie możesz też dodać klasę z parametrami:
extensions:
application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, [%appDir%], %tempDir%/cache)
Dołączanie plików
Kolejne pliki konfiguracyjne można dołączyć w sekcji includes:
includes:
- parameters.php
- services.neon
- presenters.neon
Nazwa parameters.php nie jest literówką; konfigurację można zapisać także w pliku PHP, który zwraca ją
jako tablicę:
<?php
return [
'database' => [
'main' => [
'dsn' => 'sqlite::memory:',
],
],
];
Jeśli elementy o tych samych kluczach pojawią się w kilku plikach konfiguracyjnych, zostaną nadpisane albo, w przypadku
tablic, scalone. Plik dołączony później ma wyższy priorytet niż poprzedni. Plik, w którym
wymieniona jest sekcja includes, ma wyższy priorytet niż pliki w nim dołączone.
Search
Automatyczna rejestracja usług w kontenerze DI znacząco upraszcza pracę. Nette automatycznie dodaje do kontenera presentery, ale równie łatwo dodasz dowolne inne klasy.
Wystarczy podać, w których katalogach (i podkatalogach) mają być wyszukiwane klasy:
search:
- in: %appDir%/Forms
- in: %appDir%/Model
Jeśli potrzebujesz tylko jednej reguły wyszukiwania, możesz pominąć listę i zapisać jej klucze bezpośrednio pod
search:
search:
in: %appDir%
Zwykle jednak nie chcemy dodawać absolutnie wszystkich klas i interfejsów, więc możemy je filtrować:
search:
- in: %appDir%/Forms
# filtrowanie po nazwie pliku (string|string[])
files:
- *Factory.php
# filtrowanie po nazwie klasy (string|string[])
classes:
- *Factory
Albo możemy wybrać klasy, które dziedziczą po co najmniej jednej z wymienionych klas albo ją implementują:
search:
- in: %appDir%
extends:
- App\*Form
implements:
- App\*FormInterface
Możesz też zdefiniować reguły wykluczające za pomocą masek nazw klas albo przodków. Jeśli klasa pasuje do reguły wykluczającej, nie zostanie dodana do kontenera DI:
search:
- in: %appDir%
exclude:
files: ...
classes: ...
extends: ...
implements: ...
Wszystkim automatycznie zarejestrowanym usługom można przypisać tagi:
search:
- in: %appDir%
tags: ...
Poza klasami search rejestruje również interfejsy mające jedną metodę create() albo get() –
jako generowane fabryki albo akcesory. Klasy, dla których w
kontenerze zarejestrowana jest już usługa tego samego typu, są pomijane, więc nie powstają duplikaty.
Scalanie
Jeśli elementy o tych samych kluczach pojawią się w kilku plikach konfiguracyjnych, zostaną nadpisane albo, w przypadku tablic, scalone. Plik dołączony później ma wyższy priorytet niż poprzedni.
| config1.neon | config2.neon | wynik |
|---|---|---|
|
|
|
Dla tablic scalaniu można zapobiec, dodając po nazwie klucza wykrzyknik:
| config1.neon | config2.neon | wynik |
|---|---|---|
|
|
|