gbprod/doctrine-specification-bundle

This package is abandoned and no longer maintained. No replacement package was suggested.

This bundle integrates Doctrine specification with Symfony

v2.1.0 2018-02-09 08:25 UTC

This package is auto-updated.

Last update: 2021-01-07 09:39:41 UTC


README

This bundle integrates doctrine-specification with Symfony.

Build Status codecov Scrutinizer Code Quality Dependency Status

Latest Stable Version Total Downloads Latest Unstable Version License

Installation

Download bundle using composer :

composer require gbprod/doctrine-specification-bundle

Declare in your app/AppKernel.php file:

<?php
// app/AppKernel.php

public function registerBundles()
{
    $bundles = array(
        // ...
        new GBProd\DoctrineSpecificationBundle\DoctrineSpecificationBundle(),
        // ...
    );
}

Create your specification and your expression builder

Take a look to Specification and Doctrine Specification libraries for more informations.

Create a specification

<?php

namespace GBProd\Acme\CoreDomain\Specification\Product;

use GBProd\Specification\Specification;

class IsAvailable implements Specification
{
    public function isSatisfiedBy($candidate): bool
    {
        return $candidate->isSellable() 
            && $candidate->expirationDate() > new \DateTime('now')
        ;
    }
}

Create a query factory

<?php

namespace GBProd\Acme\Infrastructure\Doctrine\QueryFactory\Product;

use GBProd\DoctrineSpecification\QueryFactory\Factory;
use GBProd\Specification\Specification;
use Doctrine\ORM\QueryBuilder;

class IsAvailableFactory implements Factory
{
    public function create(Specification $spec, QueryBuilder $qb)
    {
        return $qb->expr()
            ->andx(
                $qb->expr()->eq('sellable', "1"),
                $qb->expr()->gt('expirationDate', (new \DateTime('now'))->format('c'))
            )
        ;
    }
}

Configuration

Declare your factory

# src/GBProd/Acme/AcmeBundle/Resource/config/service.yml

services:
    acme.doctrine.query_factory.is_available:
        class: GBProd\Acme\Infrastructure\Doctrine\QueryFactory\Product\IsAvailableFactory
        tags:
            - { name: doctrine.query_factory, specification: GBProd\Acme\CoreDomain\Specification\Product\IsAvailable }

Inject handler in your repository class

# src/GBProd/Acme/AcmeBundle/Resource/config/service.yml

services:
    acme.product_repository:
        class: GBProd\Acme\Infrastructure\Product\DoctrineProductRepository
        arguments:
            - "@doctrine.orm.entity_manager"
            - "@gbprod.doctrine_specification_handler"
<?php

namespace GBProd\Acme\Infrastructure\Product;

use Doctrine\Common\Persistence\ObjectManager;
use GBProd\DoctrineSpecification\Handler;
use GBProd\Specification\Specification;

class DoctrineProductRepository implements ProductRepository
{
    private $em;

    private $handler;

    public function __construct(ObjectManager $em, Handler $handler)
    {
        $this->em      = $em;
        $this->handler = $handler;
    }

    public function findSatisfying(Specification $specification)
    {
        $qb = $this
            ->em
            ->getRepository('GBProd\Acme\CoreDomain\Product\Product')
            ->createQueryBuilder('p')
        ;
        
        return $this->handler->handle($specification, $qb);
    }
}

Usage

<?php

$products = $productRepository->findSatisfying(
    new AndX(
        new IsAvailable(),
        new IsLowStock()
    )
);