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
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
- Repository Implementations - SQL and InMemory filtering