これはPHPで仕様パターンを実装するのを手助けするライブラリです。
メモリー上での検証、メモリー上およびORMでの選択、および仕様の合成を提供します。
composer require ngmy/specification
AbstractSpecification
クラスを継承しあなたの仕様クラスを作成します。
そしてisSatisfiedBy
メソッドを実装します。
このメソッドに仕様を満たす条件を記述します。
さらに@extends
アノテーションでisSatisfiedBy
メソッドが期待するオブジェクトの型を記述しておくと静的解析が捗ります。
<?php
declare(strict_types=1);
use Ngmy\Specification\AbstractSpecification;
/**
* 人気ユーザー仕様。
*
* @extends AbstractSpecification<User>
*/
class PopularUserSpecification extends AbstractSpecification
{
/**
* {@inheritdoc}
*/
public function isSatisfiedBy($candidate): bool
{
return $candidate->getVotes() > 100;
}
}
isSatisfiedBy
メソッドに検証したいオブジェクトを渡して呼び出すことで、
そのオブジェクトが仕様を満たすかどうかを検証できます。
$spec = new PopularUserSpecification();
$spec->isSatisfiedBy($user);
もちろん選択にも使えます。
$spec = new PopularUserSpecification();
$popularUsers = array_filter(function (User $users) use ($spec): void {
return $spec->isSatisfiedBy($user);
}, $users);
applyToEloquent
メソッドを実装します。
このメソッドにwhere
メソッド等で選択条件を記述します。
use Illuminate\Contracts\Database\Eloquent\Builder;
/**
* {@inheritdoc}
*/
public function applyToEloquent(Builder $query): void
{
$query->where('votes', '>', 100);
}
applyToEloquent
メソッドにEloquentビルダーを渡して呼び出すことで、クエリーに選択条件を追加できます。
$query = User::query(); // UserはあなたのEloquentモデルです
$spec = new PopularUserSpecification();
$spec->applyToEloquent($query);
$popularUsers = $query->get();
applyToDoctrine
メソッドを実装します。
このメソッドにandWhere
メソッド等で選択条件を記述します。
use Doctrine\ORM\QueryBuilder;
use Ngmy\Specification\Support\DoctrineUtils;
/**
* {@inheritdoc}
*/
public function applyToDoctrine(QueryBuilder $queryBuilder): void
{
$queryBuilder->andWhere($queryBuilder->expr()->gt(
DoctrineUtils::getRootAliasedColumnName($queryBuilder, 'votes'),
DoctrineUtils::createUniqueNamedParameter($this, $queryBuilder, 100),
));
}
applyToDoctrine
メソッドにクエリービルダーを渡して呼び出すことで、クエリーに選択条件を追加できます。
/** @var \Doctrine\ORM\EntityManager $entityManager */
$queryBuilder = $entityManager->createQueryBuilder();
$queryBuilder->select('u')->from(User::class, 'u'); // UserはあなたのDoctrineエンティティーです
$spec = new PopularUserSpecification();
$spec->applyToDoctrine($queryBuilder);
$popularUsers = $queryBuilder->getQuery()->getResult();
仕様をAND、OR、NOTで合成できます。
仕様を合成するとisSatisfiedBy
メソッドやapplyToEloquent
、applyToDoctrine
メソッドに記述した条件も合成されます。
仕様のand
メソッドに別の仕様のインスタンスを渡して呼び出すことで、2つの仕様をANDした新しい仕様を生成できます。
$spec1 = new Specification1();
$spec2 = new Specification2();
$spec3 = $spec1->and($spec2);
仕様のor
メソッドに別の仕様のインスタンスを渡して呼び出すことで、2つの仕様をORした新しい仕様を生成できます。
$spec1 = new Specification1();
$spec2 = new Specification2();
$spec3 = $spec1->or($spec2);
仕様のnot
メソッドを呼び出すことで、自分自身をNOTした新しい仕様を生成できます。
$spec1 = new Specification1();
$spec2 = $spec1->not();
- ngmy/php-specification-example
- このプロジェクトはPHP Specificationを使用して仕様パターンを実装するコード例です。
ドメイン駆動設計のアプローチに従って書かれており、仕様とリポジトリーを組み合わせるコード例があります。
ORMにはEloquentとDoctrineを使用しています。
- このプロジェクトはPHP Specificationを使用して仕様パターンを実装するコード例です。
PHP SpecificationはMITライセンスの下で提供されるオープンソースソフトウェアです。