Форк. Упростил маленько, избавился от лишних зависимостей и т.п.
Интересный пример работы Symfony + Битрикс. Но на мой взгляд, перекручено с абстракциями. Что не отменяет качественной работы автора оригинального пакета.
Добавить в composer.json
:
"repositories": [
{
"type": "git",
"url": "https://github.com/proklung/bitrix-orm-bundle"
}
]
Выполнить:
$ composer require proklung/bitrix-orm-bundle
- Определение необходимых параметров моделей bitrix-orm через аннотации
- Автоматический поиск моделей, имеющих аннотации, поддерживаемые бандлом
- Автоматическая регистрация репозиториев как сервисов
- Автоматическое заполнение зависимостей модели
- Кеширование объектов в памяти (использование везде одного и того же объекта)
- Встроенное кеширование битрикс (в т.ч. с использованием тегов)
Файлы с аннотациями подгружаются из всех папок в директории src
проекта, имеющих название Model
(и их поддиректориях).
Каждая аннотация имеет параметры:
factory
- класс фабрики моделей. Обязательный параметрrepository
- класс репозитория. Является обязательным для всех аннотаций, кромеCatalogGroup
иHlbReference
, что классы репозиториев для остальных моделей, указанные по умолчанию, являются абстрактными
Аннотация для элементов инфоблоков
Список параметров:
iblockType
- тип инфоблока (IBLOCK_TYPE_ID
). Обязательный параметрiblockCode
- код инфоблока (CODE
). Обязательный параметр
Аннотация для разделов инфоблоков
Список параметров:
iblockType
- тип инфоблока (IBLOCK_TYPE_ID
). Обязательный параметрiblockCode
- код инфоблока (CODE
). Обязательный параметр
Аннотация для собственных таблиц
Список параметров:
table
- класс, расширяющийBitrix\Main\Entity\DataManager
. Обязательный параметр
Аннотация для элементов HL-блоков
Список параметров:
hlBlockName
- Имя HL-блока, которому принадлежит данная модель. Обязательный параметрentityCache
(bool) - Использование хака, ускоряющего инициализацию hl-блоков путем кеширования hlblockentity. По умолчанию включен
Аннотация для элементов HL-блоков-справочников
Список параметров:
hlBlockName
- Имя HL-блока, которому принадлежит данная модель. Обязательный параметрentityCache
(bool) - Использование хака, ускоряющего инициализацию hl-блоков путем кеширования hlblockentity. По умолчанию включен
Аннотация для типов цен. Дополнительных параметров нет.
Данные аннотации работают только тогда, когда задана аннотация "фабрики и репозитория".
При указании этих аннотаций регистрируются сервисы, являющиеся слоями кеширования.
RepositoryRegistry
в таком случае возвращает данный сервис вместо репозитория.
Работают данные слои на ReflectionClass
следующим образом:
- Заданы методы
add
,update
,delete
,deleteById
, которые проксируются в репозиторий. При этом в объектном кеше удаляется/обновляется/добавляется элемент - Для остальных методов:
- Если заданы
excludedMethods
, то данные методы просто проксируются в репозиторий - Происходит анализ входных параметров с помощью
\ReflectionMethod
, вызов метода, кеширование результата:- Если количество параметров == 1, то
- Если имя параметра
id
, то метод считается "получением элемента по ID" для BitrixCache на результат вешаетсяtag . ':' . $id
- Если имя параметра
xmlId
, то метод считается "получением элемента по XML_ID" для BitrixCache на результат вешаетсяtag . ':' . $xmlId
- Если имя параметра
code
, то метод считается "получением элемента по CODE", для BitrixCache на результат вешаетсяtag . ':' . $code
- Если параметр является объектом
BitrixArrayItemBase
, то метод считается "получением объекта/ов по родительскому объекту" (цен по офферу, остатков по офферу), для BitrixCache на результат вешаетсяcollectionTag . ':' . $item->getId()
- Если имя параметра
- Если параметров != 1, то происходит кеширование по ключу кеша = \get_class($model) . json_encode($parameters)
- Если количество параметров == 1, то
Можно указывать и Cache
и BitrixCache
, либо один из них, либо вовсе не указывать
Параметры:
class
- класс, реализующийKantShop\BitrixOrmBundle\Cache\CacheInterface
(ArrayCache
по умолчанию)excludedMethods
- массив методов репозитория, результаты которых кешироваться не будут
class
- класс, реализующийKantShop\BitrixOrmBundle\Cache\BitrixCacheInterface
(BitrixCache
по умолчанию)excludedMethods
- массив методов репозитория, результаты которых кешироваться не будутtag
- тег кешаcollectionTag
- тег коллекции элементовcacheTime
- время кеширования (1 час по умолчанию)
Данные аннотации работают только тогда, когда задана аннотация "фабрики и репозитория".
При указании этих аннотаций регистрируются сервисы, которые заполняют необходимые данные для модели.
Гидратор вызывается после получения данных из репозитория/кеша. Для каждого инстанса модели он вызывается один раз (используется \SplObjectStorage).
Если репозиторий вернул ArrayCollection
, то гидратор вызывается для каждого элемента поочередно.
Параметры:
class
- класс, реализующийKantShop\BitrixOrmBundle\HYdrator\HydratorInterface
Сервис, позволяющий получить нужный репозиторий по классу модели
<?php
use Acme\AppBundle\Model\City;
$registry = $serviceContainer->get('bitrix_orm.repository_registry');
$cityRepository = $registry->get(City::class);
Модель:
<?php
namespace Acme\AppBundle\Model;
use KantShop\BitrixOrm\Model\D7Item;
use KantShop\BitrixOrmBundle\Annotation as ORM;
use Acme\AppBundle\Repository\CityRepository;
use Acme\AppBundle\Factory\CityFactory;
use Acme\AppBundle\Hydrator\CityHydrator;
/**
* @ORM\HlbItem(
* hlBlockName="Cities",
* repository=CityRepository::class,
* factory=CityFactory::class
* )
* @ORM\BitrixCache(tag="city",cacheTime=3600)
* @ORM\Cache()
* @ORM\Hydrator(class=CityHydrator::class)
*/
class City extends D7Item
{
// необходимые свойства модели
}
Фабрика:
<?php
namespace Acme\AppBundle\Factory;
use Acme\AppBundle\Model\City;
use KantShop\BitrixOrm\Factories\D7ItemFactory;
use KantShop\BitrixOrm\Model\D7Item;
class CityFactory extends D7ItemFactory
{
public function createItem(array $data): D7Item
{
return new City($data);
}
public function getSelect(): array
{
return ['*'];
}
}
Репозиторий:
<?php
namespace Acme\AppBundle\Repository;
use KantShop\BitrixOrm\Repository\D7Repository;
class CityRepository extends D7Repository
{
}
Гидратор:
<?php
namespace Acme\AppBundle\Hydrator;
use Acme\AppBundle\Model\City;
use Acme\AppBundle\Service\StreetProvider;
use KantShop\BitrixOrmBundle\Hydrator\HydratorInterface;
class CityHydrator implements HydratorInterface
{
/**
* @var StreetProvider
*/
protected $streetProvider;
public function __construct(StreetProvider $streetProvider) {
$this->streetProvider = $streetProvider;
}
/**
* @param City $object
* @return City
*/
public function fill($object){
$object->setStreets($this->streetProvider->getCityStreets($object));
return $object;
}
}
Сервис:
<?php
namespace Acme\AppBundle\Service;
use Acme\AppBundle\Model\City;
use KantShop\BitrixOrmBundle\Registry\RepositoryRegistryInterface;
class CityService
{
protected $repository;
public function __construct(RepositoryRegistryInterface $repository)
{
$this->repository = $repository->get(City::class);
}
}
Модель:
<?php
namespace Acme\AppBundle\Model;
use KantShop\BitrixOrm\Model\IblockElement;
use KantShop\BitrixOrmBundle\Annotation as ORM;
/**
* Class Product
* @package Acme\AppBundle\Model
*
* @ORM\IblockElement(
* iblockType="catalog",
* iblockCode="products",
* factory="Acme\AppBundle\Factory\ProductFactory",
* repository="Acme\AppBundle\Repository\ProductRepository",
* )
*/
class Product extends IblockElement
{
// ...
}
Можно указать iblockСode
и iblockType
, используя константы:
<?php
namespace Acme\AppBundle\Model;
use KantShop\BitrixOrm\Model\IblockElement;
use KantShop\BitrixOrmBundle\Annotation as ORM;
use Acme\AppBundle\Enum\IblockType;
use Acme\AppBundle\Enum\IblockCode;
/**
* Class Product
* @package Acme\AppBundle\Model
*
* @ORM\IblockElement(
* iblockType=IblockType::CATALOG,
* iblockCode=IblockCode::PRODUCTS,
* factory="Acme\AppBundle\Factory\ProductFactory",
* repository="Acme\AppBundle\Repository\ProductRepository",
* )
*/
class Product extends IblockElement
{
// ...
}
Репозиторий:
<?php
namespace Acme\AppBundle\Repository;
use KantShop\BitrixOrm\Repository\IblockElementRepository;
class ProductRepository extends IblockElementRepository
{
}
Модель:
<?php
namespace Acme\AppBundle\Model;
use KantShop\BitrixOrm\Model\CatalogGroup as BaseCatalogGroup;
use KantShop\BitrixOrmBundle\Annotation as ORM;
/**
* Class CatalogGroup
* @package Acme\AppBundle\Model
*
* @ORM\CatalogGroup()
*/
class CatalogGroup extends BaseCatalogGroup
{
}
<?php
namespace Acme\AppBundle\Service;
use Acme\AppBundle\Model\City;
use Acme\AppBundle\Repository\CityRepository;
use KantShop\BitrixOrmBundle\Registry\RepositoryRegistryInterface;
class CityService
{
/**
* @var CityRepository
*/
protected $repository;
/**
* @var FileRepository
*/
protected $fileRepository;
public function __construct(RepositoryRegistryInterface $registry)
{
$this->repository = $registry->get(City::class);
$this->fileRepository = $registry->get(File::class);
}
}