openclassrooms / use-case
用例库
Requires
- php: >=8.2
- doctrine/annotations: ~2.0
- openclassrooms/cache: ^v1.1.0
Requires (Dev)
- phpunit/phpunit: ^9.6.20
This package is auto-updated.
Last update: 2024-09-06 14:55:11 UTC
README
UseCase 是一个库,提供管理用例架构中技术代码的功能,采用干净的/六角形/用例架构。
- 安全访问
- 缓存管理
- 事务上下文
- 事件
- 日志
目标是只让用例拥有功能性代码,并以优雅的方式使用注解来管理技术代码。
更多详情请参考
安装
composer require openclassrooms/use-case
或直接将包添加到 composer.json 文件中。
{ "require": { "openclassrooms/use-case": "*" } }
<?php require 'vendor/autoload.php'; use OpenClassrooms\UseCase\Application\Services\Proxy\UseCases\UseCaseProxy; //do things
实例化
UseCaseProxy 需要许多依赖。
依赖注入模式非常有帮助。
对于与 Symfony2 的实现,UseCaseBundle 更为合适。
UseCaseProxy 可以按以下方式实例化
class app() { /** * @var OpenClassrooms\UseCase\Application\Services\Proxy\UseCases\UseCaseProxyBuilder */ private $builder; /** * @var OpenClassrooms\UseCase\Application\Services\Security\Security; */ private $security; /** * @var OpenClassrooms\Cache\Cache\Cache; */ private $cache; /** * @var OpenClassrooms\UseCase\Application\Services\Transaction\Transaction; */ private $transaction; /** * @var OpenClassrooms\UseCase\Application\Services\EventSender\EventSender; */ private $event; /** * @var OpenClassrooms\UseCase\Application\Services\EventSender\EventFactory */ private $eventFactory; /** * @var Psr\Log\LoggerInterface */ private $logger; /** * @var Doctrine\Common\Annotations\Reader */ private $reader; public function method() { $useCase = $this->builder ->create(new OriginalUseCase()) ->withReader($this->reader) ->withSecurity($this->security) ->withCache($this->cache) ->withTransaction($this->transaction) ->withEventSender($this->event) ->withEventFactory($this->eventFactory) ->withLogger($this->logger) ->build(); } }
仅 UseCaseProxyBuilder::create(UseCase $useCase)
和 UseCaseProxyBuilder::withReader(AnnotationReader $reader)
是必须的。
用法
一个经典的 Clean / Hexagonal / 用例架构风格的用例如下
use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCase; use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCaseRequest; use OpenClassrooms\UseCase\BusinessRules\Responders\UseCaseResponse; class AUseCase implements UseCase { /** * @return UseCaseResponse */ public function execute(UseCaseRequest $useCaseRequest) { // do things return $useCaseResponse; } }
该库提供了 UseCase 的代理。
安全
@Security 注解允许检查访问。
use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCase; use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCaseRequest; use OpenClassrooms\UseCase\BusinessRules\Responders\UseCaseResponse; use OpenClassrooms\UseCase\Application\Annotations\Security; class AUseCase implements UseCase { /** * @Security (roles = "ROLE_1") * * @return UseCaseResponse */ public function execute(UseCaseRequest $useCaseRequest) { // do things return $useCaseResponse; } }
"roles" 是必需的。
其他选项
/** * @Security (roles = "ROLE_1, ROLE_2") * Check the array of roles * * @Security (roles = "ROLE_1", checkRequest = true) * Check access for the object $useCaseRequest * * @Security (roles = "ROLE_1", checkField = "fieldName") * Check access for the field "fieldName" of the object $useCaseRequest */
缓存
@Cache 注解允许管理缓存。
use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCase; use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCaseRequest; use OpenClassrooms\UseCase\BusinessRules\Responders\UseCaseResponse; use OpenClassrooms\UseCase\Application\Annotations\Cache; class AUseCase implements UseCase { /** * @Cache * * @return UseCaseResponse */ public function execute(UseCaseRequest $useCaseRequest) { // do things return $useCaseResponse; } }
键等于 md5(serialize($useCaseRequest))
,TTL 为默认值。
其他选项
/** * @Cache (lifetime=1000) * Add a TTL of 1000 seconds * * @Cache (namespacePrefix="namespace_prefix") * Add a namespace to the id with a namespace id equals to "namespace_prefix" * * @Cache (namespacePrefix="namespace prefix", namespaceAttribute="fieldName") * Add a namespace to the id with a namespace id equals to "namespace_prefix" . "$useCaseRequest->fieldName" */
事务
@Transaction 注解为用例提供了事务上下文。
- 开始事务
- 执行
- 提交
- 在异常时回滚
use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCase; use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCaseRequest; use OpenClassrooms\UseCase\BusinessRules\Responders\UseCaseResponse; use OpenClassrooms\UseCase\Application\Annotations\Transaction; class AUseCase implements UseCase { /** * @Transaction * * @return UseCaseResponse */ public function execute(UseCaseRequest $useCaseRequest) { // do things return $useCaseResponse; } }
事件
@Event 注解允许发送事件。
必须在应用程序上下文中编写 OpenClassrooms\UseCase\Application\Services\EventSender\EventFactory 的实现。
use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCase; use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCaseRequest; use OpenClassrooms\UseCase\BusinessRules\Responders\UseCaseResponse; use OpenClassrooms\UseCase\Application\Annotations\EventSender; class AUseCase implements UseCase { /** * @Event * * @return UseCaseResponse */ public function execute(UseCaseRequest $useCaseRequest) { // do things return $useCaseResponse; } }
可以发送消息
- 执行前
- 执行后
- 在异常或所有这些情况下。
默认为 post。
事件名称为用例名称,以下划线为前缀,方法名前缀。例如,前面的示例中,名称将是:use_case.post.a_use_case
前缀可以是
- use_case.pre.
- use_case.post.
- use_case.exception.
/** * @Event(name="event_name") * Send an event with event name equals to *prefix*.event_name * (note: the name is always converted to underscore) * * @Event(methods="pre") * Send an event before the call of UseCase->execute() * * @Event(methods="pre, post, onException") * Send an event before the call of UseCase->execute(), after the call of UseCase->execute() or on exception * * @Event(name="first_event") * @Event(name="second_event") * Send two events */
日志
@Log 注解允许根据 PSR 标准 添加日志。
use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCase; use OpenClassrooms\UseCase\BusinessRules\Requestors\UseCaseRequest; use OpenClassrooms\UseCase\BusinessRules\Responders\UseCaseResponse; use OpenClassrooms\UseCase\Application\Annotations\Log; class AUseCase implements UseCase { /** * @Log * * @return UseCaseResponse */ public function execute(UseCaseRequest $useCaseRequest) { // do things return $useCaseResponse; } }
日志可以是
- 执行前
- 执行后
- 在异常或所有这些情况下。
默认为异常时。
可以指定级别,根据 PSR 的级别。默认为警告。
/** * @Log(level="error") * Log with the level 'error' * * @Log (message="message with context {foo}", context={"foo":"bar"}) * Log with standard message * * @Log(methods="pre") * Log before the call of UseCase->execute() * * @Log(methods="pre, post, onException") * Log before the call of UseCase->execute(), after the call of UseCase->execute() or on exception * * @Log(methods="pre", level="debug") * @Log(methods="onException", level="error") * Log before the call of UseCase->execute() with debug level and on exception with error level */
工作流程
执行顺序如下
预执行
- 日志(预)
- 安全
- 缓存(获取)
- 事务(开始事务)
- 事件(预)
执行后
- 缓存(保存如有必要)
- 事务(提交)
- 事件(后)
- 日志(后)
异常时
- 日志(异常时)
- 事务(回滚)
- 事件(异常时)
工具
该库提供用于分页集合的通用响应。