openclassrooms/use-case

用例库

v1.1.1 2024-08-06 14:24 UTC

This package is auto-updated.

Last update: 2024-09-06 14:55:11 UTC


README

Build Status SensioLabsInsight Coverage Status

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
 */

工作流程

执行顺序如下

预执行

  • 日志(预)
  • 安全
  • 缓存(获取)
  • 事务(开始事务)
  • 事件(预)

执行后

  • 缓存(保存如有必要)
  • 事务(提交)
  • 事件(后)
  • 日志(后)

异常时

  • 日志(异常时)
  • 事务(回滚)
  • 事件(异常时)

工具

该库提供用于分页集合的通用响应。