PHPackages                             innmind/specification - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. innmind/specification

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

innmind/specification
=====================

Interfaces allowing to compose a tree of specifications

4.1.0(1y ago)063.5k↓26.7%[2 issues](https://github.com/Innmind/Specification/issues)11MITPHPPHP ~8.1

Since Mar 19Pushed 1y ago1 watchersCompare

[ Source](https://github.com/Innmind/Specification)[ Packagist](https://packagist.org/packages/innmind/specification)[ Docs](http://github.com/Innmind/Specification)[ RSS](/packages/innmind-specification/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelog (2)Dependencies (2)Versions (14)Used By (11)

Specification
=============

[](#specification)

[![Build Status](https://github.com/innmind/specification/workflows/CI/badge.svg?branch=master)](https://github.com/innmind/specification/actions?query=workflow%3ACI)[![Type Coverage](https://camo.githubusercontent.com/3579fba3c52adc574c29731aa0400344af31133d9d5cd2a5231904ee0dd25d4d/68747470733a2f2f73686570686572642e6465762f6769746875622f696e6e6d696e642f73706563696669636174696f6e2f636f7665726167652e737667)](https://shepherd.dev/github/innmind/specification)

Library containing interfaces allowing to compose a tree of specification. As you may want to type hint the object you to test against, the interfaces does **not** enforce a method `isSatisfiedBy`, it will be up to you to create such method.

The goal here is to have a set of interfaces so a specification can be composed easily, *and* decomposed afterward.

The decomposition part is useful in the case you want to translate your specification into, let's say, a doctrine query (or anything you wish).

Implementation example
----------------------

[](#implementation-example)

```
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
```

The object `$spec` could be easily decomposed to create the given `WHERE` statement of a sql query: `WHERE name = "John" or name = "Doe" or name != "John Doe"`.

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance33

Infrequent updates — may be unmaintained

Popularity30

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity79

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~276 days

Recently: every ~306 days

Total

12

Last Release

675d ago

Major Versions

1.0.0 → 2.0.02019-01-06

2.4.0 → 3.0.02022-02-27

3.0.1 → 4.0.02024-07-06

PHP version history (5 changes)1.0.0PHP &gt;=7.0

2.0.0PHP ~7.2

2.3.0PHP ~7.2|~8.0

2.4.0PHP ~7.4|~8.0

3.0.0PHP ~8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/851425?v=4)[Baptiste Langlade](/maintainers/Baptouuuu)[@Baptouuuu](https://github.com/Baptouuuu)

---

Top Contributors

[![Baptouuuu](https://avatars.githubusercontent.com/u/851425?v=4)](https://github.com/Baptouuuu "Baptouuuu (51 commits)")

---

Tags

specificationddd

###  Code Quality

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/innmind-specification/health.svg)

```
[![Health](https://phpackages.com/badges/innmind-specification/health.svg)](https://phpackages.com/packages/innmind-specification)
```

###  Alternatives

[prooph/service-bus

PHP Enterprise Service Bus Implementation supporting CQRS and DDD

4421.4M32](/packages/prooph-service-bus)[ecotone/ecotone

Supporting you in building DDD, CQRS, Event Sourcing applications with ease.

558549.8k17](/packages/ecotone-ecotone)[prooph/event-sourcing

PHP EventSourcing library

267808.5k18](/packages/prooph-event-sourcing)[phpmentors/domain-kata

Kata for domain models

73426.9k9](/packages/phpmentors-domain-kata)[maximecolin/satisfaction

A PHP implementation of the specification pattern for DDD

3630.2k](/packages/maximecolin-satisfaction)[aura/payload

A Domain Payload implementation.

56370.4k9](/packages/aura-payload)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
