Skip to content

Specifications

The Specification Pattern encapsulates business rules into reusable, composable objects for querying data.

Purpose

Specifications serve two functions: - SQL Generation - Build complex WHERE clauses - In-Memory Filtering - Filter collections without database

Interface

interface SpecificationInterface
{
    public function toSql(): array;           // ['sql' => '...', 'params' => [...]]
    public function toInMemoryFilter(): callable;  // callable(EntityInterface): bool
}

Creating Specifications

final readonly class IsAvailableSpecification extends SpecificationAbstract
{
    public function toSql(): array
    {
        return [
            'sql' => 'status = :status',
            'params' => ['status' => BookStatus::Available->value],
        ];
    }

    public function toInMemoryFilter(): callable
    {
        return fn (EntityInterface $book): bool =>
            $book->status() === BookStatus::Available;
    }
}

Composition

Combine specifications using binary operations:

// AND - Books by author published after year
$spec = new BinaryAndSpecification(
    new AuthorSpecification('Orwell'),
    new PublishedAfterSpecification(1945)
);

// OR - Books in multiple categories
$spec = new BinaryOrSpecification(
    new CategorySpecification('Fiction'),
    new CategorySpecification('Science Fiction')
);

// NOT - All except drafts
$spec = new UnaryNotSpecification(
    new BookStatusSpecification(BookStatus::Draft)
);

Repository Integration

$books = $bookRepository->findBy($specification);

The SQL implementation uses toSql(), while InMemory uses toInMemoryFilter().

Available Operations

Binary (Two Specifications)

Operation Description
BinaryAndSpecification Both conditions true
BinaryOrSpecification At least one true
BinaryAndNotSpecification First true, second false
BinaryNandSpecification Not both true
BinaryNorSpecification Neither true
BinaryXorSpecification Exactly one true
BinaryXnorSpecification Both same (both true or both false)
BinaryImpliesSpecification If first true, second must be true

Unary (One Specification)

Operation Description
UnaryNotSpecification Inverts condition
UnaryIdentitySpecification Returns input unchanged

Constants

Operation Description
AlwaysTrueSpecification Always matches
AlwaysFalseSpecification Never matches

See Also