2017 © Pedro Peláez
 

library doctrine-specification

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

image

rikbruil/doctrine-specification

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  • Friday, March 17, 2017
  • by rikbruil
  • Repository
  • 4 Watchers
  • 40 Stars
  • 66,577 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 9 Forks
  • 12 Open issues
  • 17 Versions
  • 5 % Grown

The README.md

Doctrine Specification

Build Status Coverage Status Latest Stable Version License Scrutinizer Code Quality SensioLabsInsight, (*1)

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition., (*2)

This library started out as an adaptation of Benjamin Eberlei's blog post. I was also inspired by the Happyr Doctrine-Specification code, however this library has some small differences. The main one is that SpecificationRepository->match() does not return the results directly, but returns the query object., (*3)

Since I like Doctrine's Paginator object, I wanted to be able to use that in combination with the Specification pattern., (*4)

Note: In versions prior to 1.2 it was required to extend the SpecificationRepository class. This is no longer needed since we provide a SpecificationRepositoryTrait that you can use instead. The class is still provided for backwards compatibility reasons. There is also the SpecificationAwareInterface that you can use if you need it., (*5)

Usage

Install the latest version with composer require rikbruil/doctrine-specification, (*6)

// Not using the lib
// Note: Advertisement repository is an instance of the Doctrine default repository class
$qb = $this->em->getRepository('Advertisement')
    ->createQueryBuilder('r');

return $qb->where('r.ended = 0')
    ->andWhere(
        $qb->expr()->orX(
            'r.endDate < :now',
            $qb->expr()->andX(
                'r.endDate IS NULL',
                'r.startDate < :timeLimit'
            )
        )
    )
    ->setParameter('now', new \DateTime())
    ->setParameter('timeLimit', new \DateTime('-4weeks'))
    ->getQuery()
    ->getResult();
use Rb\Specification\Doctrine\Condition\Equals;
use Rb\Specification\Doctrine\Condition\IsNull;
use Rb\Specification\Doctrine\Condition\LessThan;
use Rb\Specification\Doctrine\Logic\AndX;
use Rb\Specification\Doctrine\Logic\OrX;
use Rb\Specification\Doctrine\Specification;

// Using the lib
$spec = new Specification([
    new Equals('ended', 0),
    new OrX(
        new LessThan('endDate', new \DateTime()),
        new AndX(
            new IsNull('endDate'),
            new LessThan('startDate', new \DateTime('-4weeks'))
        )
    )
]);

// Note: Advertisement repository is an instance that uses the SpecificationRepositoryTrait
return $this->em->getRepository('Advertisement')->match($spec)->execute();

Composition

A bonus of this pattern is composition, which makes specifications very reusable:, (*7)


use Entity\Advertisement; class ExpiredAds extends Specification { public function __construct() { $specs = [ new Equals('ended', 0), new OrX( new LessThan('endDate', new \DateTime()), new AndX( new IsNull('endDate'), new LessThan('startDate', new \DateTime('-4weeks')) ) ) ]; parent::__construct($specs); } public function isSatisfiedBy($value) { return $value === Advertisement::class; } } use Entity\User; class AdsByUser extends Specification { public function __construct(User $user) { $specs = [ new Select('u'), new Join('user', 'u'), new Equals('id', $user->getId(), 'u'), ]; parent::__construct($specs); } public function isSatisfiedBy($value) { return $value == Advertisement::class && parent::isSatisfiedBy($value); } } class SomeService { /** * Fetch Adverts that we should close but only for a specific company */ public function myQuery(User $user) { $spec = new Specification([ new ExpiredAds(), new AdsByUser($user), ]); return $this->em->getRepository('Advertisement')->match($spec)->execute(); } /** * Fetch adverts paginated by Doctrine Paginator with joins intact. * A paginator can be iterated over like a normal array or Doctrine Collection */ public function myPaginatedQuery(User $user, $page = 1, $size = 10) { $spec = new Specification([ new ExpiredAds(), new AdsByUser($user), ]); $query = $this->em->getRepository('Advertisement')->match($spec); $query->setFirstResult(($page - 1) * $size)) ->setMaxResults($size); return new Paginator($query); } }

Requirements

Doctrine-Specification requires:, (*8)

  • PHP 5.5+
  • Doctrine 2.2

License

Doctrine-Specification is licensed under the MIT License - see the LICENSE file for details, (*9)

Acknowledgements

This library is heavily inspired by Benjamin Eberlei's blog post and Happyr's Doctrine-Specification library., (*10)

The Versions

17/03 2017

dev-fix-duplication

dev-fix-duplication

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

17/03 2017

dev-master

9999999-dev

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

17/03 2017

1.2.0

1.2.0.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

04/09 2016

1.1.0

1.1.0.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

26/11 2015

1.0.10

1.0.10.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

26/11 2015

1.0.9

1.0.9.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

10/08 2015

1.0.8

1.0.8.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

28/04 2015

1.0.7

1.0.7.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

11/03 2015

1.0.6

1.0.6.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

11/03 2015

1.0.5

1.0.5.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

10/03 2015

1.0.4

1.0.4.0

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

08/03 2015
08/03 2015

1.0.0

1.0.0.0

  Sources   Download

MIT

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

07/03 2015

0.9.1

0.9.1.0

  Sources   Download

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification

07/03 2015

0.9.0

0.9.0.0

  Sources   Download

The Requires

 

The Development Requires

by Rik Bruil

repository doctrine specification