sbooker / transaction-manager
应用于应用层事务控制的抽象。
2.3.1
2024-02-06 15:44 UTC
Requires
- php: ^7.4 || ^8.0
Requires (Dev)
- phpunit/phpunit: ^9.5
Suggests
- sbooker/doctrine-transaction-handler: For usage with Doctrine ORM
- sbooker/yii2-ar-transaction-handler: For usage with Yii2 Active Record
README
应用于应用层事务控制的抽象。
安装
composer require sbooker/transaction-manager
使用示例
use Sbooker\TransactionManager\TransactionHandler; use Sbooker\TransactionManager\TransactionManager; $transactionManager = new TransactionManager(new class implements TransactionHandler { ... }); class Entity { /** * @throws \Exception */ public function update(): void { ... } }
示例 1. 创建实体
$transactionManager->transactional(function () use ($transactionManager) { $transactionManager->persist(new Entity()); });
示例 2. 仅使用TransactionManager更新实体
$transactionManager->transactional(function () use ($transactionManager, $entityId) { $entity = $transactionManager->getLocked(Entity::class, $entityId); $entity->update(); // if exception throws, transaction will be rolled back });
示例 3. 使用仓库更新实体
$transactionManager->transactional(function () use ($transactionManager, $entityRepository, $criteria) { $entity = $entityRepository->getLocked($criteria); $entity->update(); // if exception throws, transaction will be rolled back $transactionManager->save($entity); });
示例 4. 支持嵌套事务
通常,您只需要一个事务来处理单个命令(请参阅之前的示例)。通常,您在应用层服务(所谓命令处理器)中这样做。
final class CommandProcessor { private TransactionManager $transactionManager; ... /** @throws \Exception */ public function update($entityId): void { $transactionManager->transactional(function () use ($transactionManager, $entityId) { $entity = $transactionManager->getLocked(Entity::class, $entityId); $entity->update(); }); } }
当您同步地从表现层调用应用层时,它运行良好。例如,使用HTTP请求并在控制器中将它转换为命令。
但有时您需要处理与HTTP请求相同的域逻辑之前存储的命令。当然,在这种情况下,您想要保存命令执行结果。例如,如果执行失败,则进行下一次重试。在这种情况下,您需要嵌套事务,并且外层事务将不会回滚。
$commandProcessor = new CommandProcessor($transactionManager); $transactionManager->transactional(function () use ($transactionManager, $commandId, $commandProcessor) { $command = $transactionManager->getLocked(Command::class, $commandId); try { $commandProcessor->update($command->getEntityId()); $command->setSuccessExecutionState(); } catch (\Exception) { $command->setFailExecutionState(); } });
注意!
$entityId = ...; $transactionManager->transactional(function () use ($transactionManager, $entityId) { $entity = new SomeEntity($entityId); $transactionManager->persist($entity); // Depends on TransactionHandler implementation $persistedEntity may be null in same transaction with persist $persistedEntity = $transactionManager->getLocked($entityId); }
许可证
请参阅LICENSE文件。