Автоопределение класса сущности по его интерфейсу
В модуль входит несколько реализаций механизма определения имени класса сущности по интерфейсу.
Абстрактная фабрика \Nnx\Doctrine\EntityManager\OrmEntityAbstractFactory.
При использовании \Nnx\Doctrine\EntityManager\OrmEntityAbstractFactory необходимо чтобы:
- Модули должны придерживаться одинаковой структуры расположения сущностей;
- В описании используемых namespace для Doctrine\ORM\Mapping\Driver\DriverChain должен соблюдаться приоритет.
Расмотрим проект со следующей структурой:
project
vendor
nnx-service
core
src
Entity
MyEntity
CoreServiceInterface
CoreService
ext-core-module
src
Entity
MyEntity
CoreService
customVendor-service
core
src
Entity
MyEntity
CoreService
В вышеприведенном примере в модулях nnx-service\ext-core-module и nnx-service\customVendor-service сознательно повторяется структура модуля nnx-service\core.
Алгоритм определения имени класса сущности по интерфейсу следующий:
- Разбить интерфейс сущности на префикс и "путь":
- Разбиение производится по разделителю. По умолчанию это Entity (\Nnx\Service\Core\Entity\CoreServiceInterface -> ['\Nnx\Service\Core\Entity\', 'MyEntity\CoreServiceInterface'];
- Разделитель может быть задан через настройки модуля (@see \Nnx\Doctrine\Options\ModuleOptions::$entitySeparator).
- Применить к получившемуся пути паттерн (@see \Nnx\Doctrine\Options\ModuleOptions::$entityBodyNamePattern). MyEntity\CoreServiceInterface -> MyEntity\CoreService;
- Пост обработка "пути" к сущности. Можно через настройки модуля указать:
- Префикс, прибавляемый к имени сущности (@see \Nnx\Doctrine\Options\ModuleOptions::$entityNamePrefix);
- Постфикс, прибавляемый к имени сущности (@see \Nnx\Doctrine\Options\ModuleOptions::$entityNamePostfix).
- По имени интерфейса определить имя ObjectManager'a доктрины -> $objectManagerName;
- Получить список namespace сущностей, используемых в данном ObjectManager'е:
- Считается, что в качестве ObjectManager'a выступает \Doctrine\ORM\EntityManager;
- Интеграция приложения с Doctrine2 осуществляется с помощью doctrine/doctrine-orm-module;
- Получаем имя конфигурации из конфига приложения:
text $configuration = $serviceLocator->get('Config')['doctrine']['entitymanager'][$objectManagerName]['configuration'];
- По имени $configuration получаем имя используемого драйвера:
text $driver = $serviceLocator->get('Config')['doctrine']['configuration'][$configuration]['driver'];
- По имени драйвера (предполагается, что это Doctrine\ORM\Mapping\Driver\DriverChain) получаем список $namespaces:
text $namespaces = $serviceLocator->get('Config')['doctrine']['driver'][$driver]['drivers'];
- Считаем, что список $namespaces определяет приоритет при поиске класса, реализующего интерфейс сущности;
- Пробегаемся по списку $namespaces и определяем класс сущности:
- Для конкретного namespace определяем его префикс (префикс — это первый элемент массива, полученного в результате разибения namespace по разделителю @see \Nnx\Doctrine\Options\ModuleOptions::$entitySeparator);
- К префиксу подставляется "путь" к сущности, полученный в результате постобработки;
- В случае если существует класс с именем, полученным в результате конкатенации префикса для текущего namespace и "пути" к классу сущности, прекращаем поиск.
- Проверяем, что найденный класс имплементирует интерфейс, для которого происходил поиск.
Кэширование карты сущностей
Модуль реализует возможность закешировать карту сущностей для сокращения накладных расходов по автоопределению класса сущности на основе имени интерфейса:
Для этих целей предназначена консольная команда:
php public/index.php entity-map build --objectManager=doctrine.entitymanager.orm_default
Алгоритм построения кэша:
- Для ObjectManager'a c заданным именем получаем список имен классов всех сущностей;
- Для каждого класса определяем список интерфейсов (учитываются только интерфейсы, находящикся в модулях, в которых расположены сущности);
- Для каждого интерфейса пробуем получить имя класса. В случае если это возможно, то добавляем в карту (ключ имя интерфейса, значение имя класса);
- Из настроек модуля определяем кэш для сохранения (@see \Nnx\Doctrine\Options\ModuleOptions::$entityMapDoctrineCache);
- Записываем полученную карту в кэш.
В модуль включена абстрактная фабрика \Nnx\Doctrine\EntityManager\EntityMapAbstractFactory, в которой реализована работа с кэшом:
- В случае если кэш присутствует для ObjectManager'a (имя ObjectManager берется из настроек модуля, к которому принадлежит интерфейс сущности);
- В данном кэше проверяется, есть ли для искомого интерфейса класс, который его реализует.
Для очистки кэша можно использовать консольную команду:
php public/index.php entity-map clear --objectManager=doctrine.entitymanager.orm_default
Автоматическое кеширование карты сущностей
Начиная с версии 0.1.14 добавлена возможность автоматически строить кэш карты сущностей, не запуская ни каких, консольных комманд
За логику работы с автоматическим кэшированием отвечают следующие настройки модуля:
Имя параметра | Описание |
---|---|
flagAutoBuildEntityMapDoctrineCache | Флаг определяет, нужно ли автоматически собирать кэш карты сущностей |
flagDisableUseEntityMapDoctrineCache | Флаг блокирует использования системы кэширования (удобно устанавливать разработчикам во время отладки) |
excludeEntityManagerForAutoBuildEntityMap | Список имен ObjectManager'ов, для которых в автоматическом режиме (flagAutoBuildEntityMapDoctrineCache=true) никогда не строится карта сущностей. |
По умолчанию автоматическая сборка кэша для карты сущностей выключена.