innmind/specification

允许组合规范树型的接口

4.1.0 2024-07-13 14:45 UTC

This package is auto-updated.

Last update: 2024-09-13 15:12:20 UTC


README

Build Status Type Coverage

包含允许组合规范树型接口的库。由于您可能想要为测试的对象进行类型提示,接口不强制实现 isSatisfiedBy 方法,您需要自己创建此类方法。

此处的目标是拥有一个接口集合,以便可以轻松地组合规范,并且之后可以分解。

分解部分在您想要将规范转换为,比如说,一个 doctrine 查询(或任何您想要的)时很有用。

实现示例

use Innmind\Specification\{
    Specification,
    Composite,
    Operator,
    Not,
    Comparator,
    Sign,
};

class User
{
    public $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }
}

class AndSpecification implements Composite
{
    private $left;
    private $right;

    public function __construct(Specification $left, Specification $right)
    {
        $this->left = $left;
        $this->right = $right;
    }

    public function left(): Specification
    {
        return $this->left;
    }

    public function operator(): Operator
    {
        return Operator::and;
    }

    public function right(): Specification
    {
        return $this->right;
    }

    public function isSatisfiedBy(User $user): bool
    {
        return $this->left->isSatisfiedBy($user) && $this->right->isSatisfiedBy($user);
    }
}

class OrSpecification implements Composite
{
    private $left;
    private $right;

    public function __construct(Specification $left, Specification $right)
    {
        $this->left = $left;
        $this->right = $right;
    }

    public function left(): Specification
    {
        return $this->left;
    }

    public function operator(): Operator
    {
        return Operator::or;
    }

    public function right(): Specification
    {
        return $this->right;
    }

    public function isSatisfiedBy(User $user): bool
    {
        return $this->left->isSatisfiedBy($user) || $this->right->isSatisfiedBy($user);
    }
}

class NotSpecification implements Not
{
    private $specification;

    public function __construct(Specification $specification)
    {
        $this->specification = $specification;
    }

    public function specification(): Specification
    {
        return $this->specification;
    }

    public function isSatisfiedBy(User $user): bool
    {
        return !$this->specification->isSatisfiedBy($user);
    }
}

class NameSpecification implements Comparator
{
    private $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function and(Specification $specification): Composite
    {
        return new AndSpecification($this, $specification);
    }

    public function or(Specification $specification): Composite
    {
        return new OrSpecification($this, $specification);
    }

    public function not(): Not
    {
        return new NotSpecification($this);
    }

    public function property(): string
    {
        return 'name';
    }

    public function sign(): Sign
    {
        return Sign::equality;
    }

    public function value()
    {
        return $this->name;
    }

    public function isSatisfiedBy(User $user): bool
    {
        return $user->name === $this->name;
    }
}

$spec = (new NameSpecification('John'))
    ->or(new NameSpecification('Doe'))
    ->or((new NameSpecification('John Doe'))->not());
$spec->isSatisfiedBy(new User('John')); //true
$spec->isSatisfiedBy(new User('Doe')); //true
$spec->isSatisfiedBy(new User('John Doe')); //false
$spec->isSatisfiedBy(new User('42')); //true

对象 $spec 可以轻松分解以创建 SQL 查询的给定 WHERE 语句:WHERE name = "John" or name = "Doe" or name != "John Doe"