beta / bx.model.ext
扩展模型
1.0.1
2022-02-16 13:39 UTC
Requires
- beta/bx.model: ^1.0
Requires (Dev)
- beta/bx.data.provider: ^1.4
- beta/data.provider: ^1.2
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
- vimeo/psalm: ^4.20
This package is auto-updated.
Last update: 2024-09-17 13:42:45 UTC
README
此模块包含一系列用于模型服务的装饰器
- LazyModelService - 实现按需加载数据的机制。
- StorageModelService - 实现Indenty map机制,包含存储已请求的对象的存储库。
- TransactionModelService - 包含记录/删除操作的存储库,用于创建总事务。
LazyModelService
包含模型服务装饰器(LazyModelService)、模型装饰器(LazyModel)和用于按需大量加载数据的独立集合(LazyModelCollection)。
工作示例
use Bx\Model\Ext\DataHelper; use Bx\Model\Ext\LazyModelService; use Bx\Model\Ext\LazyModel; use Bitrix\Main\Loader; Loader::includeModule('bx.model.ext'); $someServiceModel = new SomeServiceModel(); // некий сервис для работы с моделями $lazyServiceModel = new LazyModelService( $someServiceModel, SomeModel::class, // класс модели данных 'ID' // первичный ключ ); $collection = $lazyServiceModel->getList([ 'select' => ['ID'], ]); // [['ID' => 1], ['ID' => 2], ['ID' => 3]] $firstModel = $collection->first(); $firstModel->load(); // запрашиваем все данные по данной модели DataHelper::load($firstModel); // альтернативный способ запроса данных модели print_r(iterator_to_array($firstModel)); // ['ID' => 1, 'NAME' => 'first'...] print_r(iterator_to_array($collection)); // [['ID' => 1, 'NAME' => 'first'...], ['ID' => 2], ['ID' => 3]] $collection->load(); // запрашиваем все данные по моделям коллекции DataHelper::load($collection); // альтернативный способ запроса данных коллекции print_r(iterator_to_array($collection)); // [['ID' => 1, 'NAME' => 'first'...], ['ID' => 2, 'NAME' => 'second'...], ['ID' => 3, 'NAME' => 'third'...]] var_dump($first instanceof SomeModel); // false var_dump($first instanceof LazyModel); // true // данный метод позволяет получить инкапсулированную модель var_dump($first->getOriginalObject() instanceof SomeModel); // true /** * альтернативный метод для запроса инкапсулированной модели, * в отличии от первого метода позволяет пройти по всей цепочки * декоратов и извлечь исходную модель * **/ var_dump(DataHelper::extractOriginalObject($first) instanceof SomeModel); // true var_dump($lazyServiceModel->getOriginalObject() instanceof SomeServiceModel); // true var_dump(DataHelper::extractOriginalObject($lazyServiceModel) instanceof SomeServiceModel); // true
StorageModelService
包含模型服务装饰器(LazyModelService),它会保存请求过的模型列表,并在重复请求相同模型时从内部存储中提取它们。这样,可以避免对象的重复,并减少对数据源的数据访问次数。默认的存储机制使用LRU缓存。
工作示例
use Bx\Model\Ext\StorageModelService; use Bx\Model\Ext\Common\ModelStorage; use Bx\Model\Ext\Common\LruRemoveStrategy; use Bitrix\Main\Loader; Loader::includeModule('bx.model.ext'); $someServiceModel = new SomeServiceModel(); // некий сервис для работы с моделями $modelSotrage = new ModelStorage( // создаем хранилище для моделей new LruRemoveStrategy(), // стратегия чистки кеша 'ID', // первичный ключ [], // элементы для добавления в хранилище 1000 // максимальное количество элементов в хранилище ); $storageServiceModel = new StorageModelService( $someServiceModel, SomeModel::class, 'ID', $modelSotrage ); $model1 = $storageServiceModel->getById(1); $model2 = $storageServiceModel->getById(1); $model3 = $storageServiceModel->getList(['filter' => ['=ID' => 1]])->first(); var_dump($model1 === $model2); // true, один и тот же объект var_dump($model1 === $model3); // true, один и тот же объект
TransactionModelService
包含模型服务装饰器(TransactionModelService)和模型装饰器(StateModel),允许跟踪模型中的数据变化。所有写入和删除操作都收集到单独的操作存储库中,稍后可以作为一个单一事务启动,或实现大量数据更新的场景,或实现工作单元模式。
工作示例
use Bx\Model\Ext\DataHelper; use Bx\Model\Ext\TransactionModelService; use Bx\Model\Ext\Common\OperationHolder; use Bitrix\Main\Loader; Loader::includeModule('bx.model.ext'); $someServiceModel = new SomeServiceModel(); // некий сервис для работы с моделями $operationHolder = new OperationHolder(); // хранилище операций $transactionServiceModel = new TransactionModelService( $operationHolder, $someServiceModel, SomeModel::class ); $model = $transactionServiceModel->getById(1); // ['ID' => 1, 'NAME' => 'Original name'] $model->setName('Name 1'); $model['NAME'] = 'Name 2'; var_dump($model->isChanged()); //true $state = $model->offsetGetState('NAME'); // хранище состояний указанного поля print_r(iterator_to_array($state)); // ['Name 2', 'Name 1', 'Original name'] var_dump($model->getName()); // 'Name 2' var_dump($model['NAME']); // 'Name 2' $model->loadPrevState('NAME'); // загружаем предыдущее состояние поля var_dump($model->getName()); // 'Name 1' var_dump($model['NAME']); // 'Name 1' $model->loadPrevState('NAME'); // загружаем предыдущее состояние поля var_dump($model->getName()); // 'Original name' var_dump($model['NAME']); // 'Original name' $model->loadNexState('NAME'); // загружаем следующее состояние поля var_dump($model->getName()); // 'Name 1' var_dump($model['NAME']); // 'Name 1' $model->loadOriginalState(); // загружаем исходное состояние всех полей модели var_dump($model->getName()); // 'Original name' var_dump($model['NAME']); // 'Original name' $model->loadLastState(); // загружаем последнее состояние всех полей модели var_dump($model->getName()); // 'Name 2' var_dump($model['NAME']); // 'Name 2' // запрашиваем измененные данные var_dump($model->getChangesData()); // ['NAME' => 'NAME 2'] $result = $transactionServiceModel->save($model); // получаем экземпляр TransactionResult, данная операция добавлена в хранилище операций, но не была применена $result->commit(); // мы можем применить данную операцию на месте DataHelper::commit($result); // или применить ее таким способом // запрос всех опреаций для указанного сервиса $operationHolder->getOperationList(SomeServiceModel::class); // запрос опреаций создания для указанного сервиса $operationHolder->getCreateOperationList(SomeServiceModel::class); // запрос опреаций обновления для указанного сервиса $operationHolder->getUpdateOperationList(SomeServiceModel::class); // запрос опреаций создания для указанного сервиса $operationHolder->getRemoveOperationList(SomeServiceModel::class); $operationHolder->actualizeOperations(); // данный метод позволяет отчистить хранилище от ранее выполненных операции и устанить конфликтующие операции $operationHolder->commit(); // выполнить все опреции из хранилища и отчистить хранилище DataHelper::commit($operationHolder); // альтернативный метод выполнения операций из хранилища