Определения на услуги
Конфигурацията е мястото, където даваме указания на контейнера DI как да сглобява отделните услуги и как да ги свързва с други зависимости. Nette предоставя много ясен и елегантен начин за постигане на това.
Разделът services
в конфигурационния файл NEON е мястото, където
дефинираме нашите потребителски услуги и техните конфигурации. Нека
разгледаме прост пример за дефиниране на услуга с име database
,
която представлява инстанция на класа PDO
:
Тази конфигурация води до следния фабричен метод в контейнера DI:
Имената на услугите ни позволяват да се позоваваме на тях в други
части на конфигурационния файл, като използваме формата @serviceName
.
Ако няма нужда да даваме име на услугата, можем просто да
използваме точка:
За да извлечем услуга от контейнера DI, можем да използваме метода
getService()
с името на услугата като параметър или метода
getByType()
с типа на услугата:
Създаване на услуги
Най-често създаваме услуга, като просто инстанцираме определен клас. Например:
Ако трябва да разширим конфигурацията с допълнителни ключове, дефиницията може да се разшири на няколко реда:
Ключът create
има псевдоним factory
, като и двете версии са
често срещани в практиката. Въпреки това препоръчваме да използвате
create
.
Аргументите на конструктора или методът за създаване могат
алтернативно да бъдат записани в ключа arguments
:
Не е задължително услугите да се създават само чрез просто инстанциране на клас; те могат да се създават и в резултат на извикване на статични методи или методи на други услуги:
Обърнете внимание, че за опростяване вместо ->
, използваме
::
, вж. изразните средства. Тези фабрични
методи се генерират:
Контейнерът DI трябва да знае типа на създадената услуга. Ако създаваме услуга с помощта на метод, който няма определен тип на връщане, трябва изрично да споменем този тип в конфигурацията:
Аргументи
Предаването на аргументи към конструкторите и методите става по начин, много подобен на този в обикновения PHP:
За по-добра четимост можем да изписваме аргументите на отделни редове. В този формат използването на запетаи не е задължително:
Можете също така да назовете аргументите, което ви позволява да не се притеснявате за реда им:
Ако желаете да пропуснете някои аргументи и да използвате стойностите им по подразбиране или да вмъкнете услуга чрез автоматично свързване, използвайте долна черта:
Аргументите могат да бъдат услуги, параметри и много други, вижте изразни средства.
Настройка
В раздела setup
дефинираме методите, които трябва да се извикат
при създаването на услугата.
В PHP това би изглеждало така:
В допълнение към извикването на методи, можете също така да предавате стойности на свойствата. Добавянето на елемент към масив също се поддържа, но трябва да го оградите в кавички, за да избегнете колизия със синтаксиса на NEON:
В PHP това ще се преведе като:
В настройката можете също така да извиквате статични методи или
методи на други услуги. Ако трябва да предадете текущата услуга като
аргумент, използвайте @self
:
Обърнете внимание, че за опростяване вместо ->
, използваме
::
, вижте изразните средства. Това генерира
следния фабричен метод:
Средства за изразяване
Nette DI ни предоставя изключително богати възможности за изразяване, което ни позволява да изразим почти всичко. В конфигурационните файлове можем да използваме параметри:
Можем също така да създаваме обекти, да извикваме методи и функции:
Услугите се наричат по име или по тип:
Използвайте синтаксис на първокласни извиквания:
Използвайте константи:
Извикванията на методите могат да бъдат верижно свързани, точно
както в PHP. За улеснение, вместо ->
, използваме ::
:
Тези изрази могат да се използват навсякъде при създаване на услуги, в аргументи, в секцията за настройка или в параметри:
Специални функции
В рамките на конфигурационните файлове можете да използвате тези специални функции:
not()
за отричане на стойностиbool()
,int()
,float()
,string()
за привеждане на типове без загубиtyped()
за генериране на масив от всички услуги от определен типtagged()
за създаване на масив от всички услуги с даден етикет
В сравнение с конвенционалното типизиране в PHP, като например
(int)
, типизирането без загуби ще хвърля изключение за нецифрови
стойности.
Функцията typed()
създава масив от всички услуги от определен тип
(клас или интерфейс). Тя изключва услуги с изключено автоматично
свързване. Могат да бъдат зададени няколко типа, разделени със
запетаи.
Можете също така автоматично да подадете масив от услуги от определен тип като аргумент, като използвате автоподразбиране.
Функцията tagged()
създава масив от всички услуги с определен
етикет. Могат да бъдат изброени няколко тага, разделени със запетаи.
Автоматично окабеляване
Ключът autowired
ви позволява да променяте поведението на
автоматичното свързване за определена услуга. За повече подробности
вижте главата за автоматичното свързване.
Мързеливи услуги
Мързеливото зареждане е техника, която отлага създаването на услуга до момента, в който тя действително е необходима. Можете да активирате създаването на мързеливи услуги глобално в конфигурацията за всички услуги едновременно. За отделните услуги това поведение може да бъде пренаписано:
Когато дадена услуга е дефинирана като мързелива, заявката за нея от DI контейнера ще връща специален прокси обект. Този прокси обект изглежда и се държи като действителната услуга, но истинската инициализация (извикване на конструктор и настройка) ще се извърши само при първото извикване на някой от нейните методи или свойства.
Ленивото зареждане може да се използва само за дефинирани от потребителя класове, но не и за вътрешни PHP класове. Изисква PHP 8.4 или по-нова версия.
Етикети
Етикетите се използват за добавяне на допълнителна информация към услугите. Можете да зададете един или повече тагове на услуга:
Таговете могат да носят и стойности:
За извличане на всички услуги с определени тагове можете да
използвате функцията tagged()
:
В контейнера DI можете да получите имената на всички услуги с
определен таг, като използвате метода findByTag()
:
Режим на инжектиране
Използването на флага inject: true
активира предаването на
зависимости чрез публични променливи с анотацията inject и методите inject*().
По подразбиране inject
е активиран само за презентатори.
Промени в услугата
Контейнерът DI съдържа много услуги, добавени чрез вградени или потребителски разширения. Можете да променяте
дефинициите на тези услуги директно в конфигурацията. Например, можете
да промените класа на услугата application.application
, която традиционно
е Nette\Application\Application
, на нещо друго:
Флагът alteration
е информативен и показва, че просто модифицираме
съществуваща услуга.
Можем също така да допълним настройката:
Когато презаписвате услуга, може да искате да премахнете
оригиналните аргументи, елементи на настройката или тагове, което е
мястото, където reset
е полезен:
Ако искате да премахнете услуга, добавена от разширение, можете да го направите по следния начин: