此包已被弃用且不再维护。作者建议使用ammit-php/ammit包代替。

[DDD] 稳定的框架无关命令解析器

安装: 758

依赖: 0

建议者: 0

安全性: 0

星标: 3

关注者: 5

分支: 2

公开问题: 7

类型:项目

v1.0.0-beta5 2017-05-04 06:56 UTC

README

ef90f812-c184-11e6-99da-add0658f2baf.png

# Ammit

PHP7 DDD v1.0.0 beta v2.0.0 never SemVer Build Status Code Quality Code Coverage Dependency Status

一个轻量级、稳定且与框架无关的命令解析器库

目前正在进行战斗测试(尚未标记为1.0.0)

  1. 库的功能
  2. 如何使用它?
  3. 库不做什么?
  4. 为什么?
  5. 它是如何工作的?
  6. 实用主义?
  7. 想要贡献?
  8. Ammit?

命令 是一个简单的、命名良好的 DTO,反映了用户 意图

因此,它应该是 不可变的

RegisterUserCommand.png

  • RegisterUserCommand
  • DisableUserCommand
  • BookCargoCommand

库的功能是什么?

  • 它提供了一种辅助工具,可以轻松地从PSR-7 HTTP请求(或CLI输入)中提取标量数据,以便实例化一个不可变的命令。
  • 它允许实现干净的命令(没有公共字段)。
  • 它设计为一个简单的、无UI验证框架依赖的UI验证框架。
  • 它设计用来简化UI验证与领域验证的关注点分离

Simple Spec

如何使用它?

composer require ammit-php/ammit

示例

实现一个 RegisterUserCommandResolver,它将PSR-7 ServerRequestInterface 映射到一个 RegisterUserCommand。在创建 RegisterUserCommand 之前,它将执行UI验证。

RegisterUserController.php

$registerUserCommandResolver = new RegisterUserCommandResolver();
try {
    $command = $registerUserCommandResolver->resolve($request);
} catch (AbstractNormalizableCommandResolverException $e) {
    // Return a JSON error following jsonapi.org's format
    // @see https://jsonapi.fullstack.org.cn/examples/#error-objects-basics
    return JsonResponse::fromJsonString(
        json_encode(
            $e->normalize()
        ), 
        406
    );
}

try {
    $this->userService->registerUser($command);
} catch(DomainException $e) {
   // ...
}
// ...

RegisterUserCommandResolver.php

/**
 * Resolve a PSR-7 Request into a RegisterUserCommand (Data Transfer Object)
 */
class RegisterUserCommandResolver extends AbstractPureCommandResolver
{
    /**
     * @inheritdoc
     */
    public function resolve(ServerRequestInterface $request): RegisterUserCommand
    {
        $commandConstructorValues = $this->resolveRequestAsArray($request);

        // We are using variadic function here (https://wiki.php.net/rfc/variadics)
        return new RegisterUserCommand(...$commandConstructorValues);
    }

    /**
     * @inheritDoc
     */
    protected function validateThenMapAttributes(ServerRequestInterface $request): array
    {
        // $id = $_GET['id']
        $id = $this->queryStringValueValidator->mustBeString(
            $request,
            'id'
        );

        // $firstName = $_POST['firstName']
        $firstName = $this->attributeValueValidator->mustBeString(
            $request,
            'firstName'
        );

        // $lastName = $_POST['lastName']
        $lastName = $this->attributeValueValidator->mustBeString(
            $request,
            'lastName'
        );

        // $email = $_POST['email']
        $email = $this->attributeValueValidator->mustBeString(
            $request,
            'email'
        );

        // Will be injected directly in RegisterUserCommand::__construct(...$args)
        // as variadic function
        $commandConstructorValues = [
            $id,
            $firstName,
            $lastName,
            $email
        ];

        return $commandConstructorValues;
    }
}

在Symfony中使用它:https://symfony.ac.cn/doc/current/request/psr7.html

在Laravel中使用它:待定

公共API

纯扩展 AbstractPureCommandResolver
原始 $_GET $_POST
$this->rawValueValidator $this->queryStringValueValidator $this->attributeValueValidator
布尔值 ->mustBeBoolean(...)
字符串 ->mustBeString(...)
整数 ->mustBeInteger(...)
浮点数 ->mustBeFloat(...)
数组 ->mustBeArray(...)
日期 ->mustBeDate(...)
日期时间 ->mustBeDateTime(...)
实用扩展 AbstractPragmaticCommandResolver
原始 $_GET $_POST
$this->rawValueValidator $this->queryStringValueValidator $this->attributeValueValidator
与 AbstractPureCommandResolver 相同 相同
UUID ->mustBeUuid(...)
长度 ->mustHaveLengthBetween(...)
电子邮件 ->mustBeEmailAddress(...)
正则表达式 ->mustBeValidAgainstRegex(...)

库不做什么?

  • 它不是设计为Symfony Form Component 的替代品。
  • 它并不是为了创建复杂的验证而设计的。它的目标是验证简单的标量。然而,它仍然允许用于原型设计/快速应用程序开发的“实用”复杂UI验证。
  • 它并不是为了使用PHP反射而设计的。它仅意味着使用命令构造函数。

为什么?

我们曾使用Symfony 表单组件来映射和验证HTTP请求到我们的命令。

但它太复杂了,并且过于原始。而且很容易将我们的领域验证放入表单类型中,然后“忘记”将其放回我们的领域。

此外,我们还希望预见不可变类

它是如何工作的?

Complete Spec

它使用内部 \Closure 来捕获所有 \Exception。否则,它只会显示一个验证问题。而我们希望像表单一样一次性看到所有验证问题。

实用吗?

你可能需要在UI中放置一些领域验证。有时在原型设计时,我们需要做一些快速应用程序开发,并且知道我们将在不久的将来偿还我们的技术债务。

使用 Ammit,你会使用我们的 AbstractPragmaticCommandhenResolver实用)而不是我们的 AbstractPureCommandResolver)辅助器。这将允许你使用更复杂的验证,例如,例如,使用 uuid 验证。

$email = $attributeValueValidator->mustBeUuid(
    $request,
    'id'
);

缺少验证。你仍然可以注入自己的。

想要贡献吗?

阅读 UBIQUITOUS_LANGUAGE_DICTIONARY.md

初始化Docker容器:docker-compose up -d

Composer安装:docker-compose run --rm composer install

使用容器:docker/bin/php -v(首先执行chmod +x docker/bin/php

添加单元测试后:docker/bin/php bin/atoum

Ammit是什么?

Ammit,一个古埃及女神,参与心脏称重。她吞噬了被判定为不够纯洁,无法继续前往奥西里斯和永生之旅的人类灵魂。