emarref / spec
Implementation of the Specification pattern.
v1.0.0
2020-07-03 09:54 UTC
Requires (Dev)
- phpunit/phpunit: ^9.2
This package is auto-updated.
Last update: 2024-11-29 06:47:09 UTC
README
This library implements the Specification Pattern for use in any project.
Create composable logic by encapsulating decisions in a class that adheres to the SpecificationInterface.
Install
$ composer require emarref/spec
Usage
Given the following specifications:
<?php use Emarref\Spec\SpecificationInterface; use Emarref\Spec\LogicalSpecificationTrait; class MorningSpecification implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $hour = (int) $subject->format('G'); return $hour < 12; } } class AfternoonSpecification implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $hour = (int) $subject->format('G'); return $hour > 12 && $hour < 18; } } class NightSpecification implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $hour = (int) $subject->format('G'); return $hour > 17; } }
We can test if a date is in the morning:
<?php $morning = new \DateTime('8am'); $isMorning = new MorningSpecification(); $isMorning->isSatisfiedBy($morning); // true
or afternoon:
<?php $isAfternoon = new AfternoonSpecification(); $isAfternoon->isSatisfiedBy($morning); // false
We can chain specs together:
<?php $night = new \DateTime('11pm'); $isMorning->or($isAfternoon)->isSatisfiedBy($morning); // true $isMorning->or($isAfternoon)->isSatisfiedBy($night); // false
Chaining can be deep:
<?php $isMorning->or($isAfternoon->andNot($isNight))->isSatisfiedBy($morning); // true
Business logic can be encapsulated by custom specs. Create a class that
implements the Emarref\Spec\SpecificationInterface
. Use the Emarref\Spec\LogicalSpecificationTrait
to implement most of the boilerplate.
<?php class StoreIsOpen implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $isMorning = new MorningSpec(); $isAfternoon = new AfternoonSpec(); return $isMorning->or($isAfternoon)->isSatisfiedBy($subject); } } $storeIsOpen = new StoreIsOpen(); $storeIsOpen->isSatisfiedBy(new DateTime('10am')); // true $storeIsOpen->isSatisfiedBy(new DateTime('11pm')); // false