Open webdevilopers opened 8 years ago
My implementation is not implemented, that repo was to TRY to and implement the pattern... wasn't very successful.
Tried any of the others @mbrevda ? What was missing for success?
The HappyDoctrineSpecification works. I've been using in in prod for over a year. I will soon tag version 1.0.
It wasn't so much the spec part, as much as I wanted a Specification that can be turned in a query. That proved to be quite difficult and I ran out of time.
On Wed, Jun 22, 2016, 7:14 PM Tobias Nyholm notifications@github.com wrote:
The HappyDoctrineSpecification works. I've been using in in prod for over a year. I will soon tag version 1.0.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/webdevilopers/php-ddd/issues/17#issuecomment-227795606, or mute the thread https://github.com/notifications/unsubscribe/AAR4jP1GbTEHNnWUzA60lKsoEDAHXGOXks5qOV9SgaJpZM4I7tPY .
@Nyholm Can you say something about your directory/namespacing schema for the custom specs?
Another Bundle I found is RulerZ
by @K-Phoen:
Using RulerZ, the two previous repositories can be refactored:
<?php
interface CompanyRepository
{
public function save(Company $company);
public function find($slug);
public function matchingSpec(Specification $spec);
}
class DoctrineCompanyRepository extends EntityRepository implements CompanyRepository
{
// ...
public function matchingSpec(Specification $spec)
{
$qb = $this->createQueryBuilder('c');
return $this->rulerz->filterSpec($qb, $spec);
}
}
class InMemoryCompanyRepository implements CompanyRepository
{
private $companies = [];
// ...
public function matchingSpec(Specification $spec)
{
return $this->rulerz->filterSpec($this->companies, $spec);
}
}
It is also possible to use the Specs for filtering directly inside Symfony Forms:
<?php
class CompanySearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$terms = $builder
->create('who')
->addModelTransformer(
new SpecToStringTransformer(Spec\CompanyName::class, 'terms')
);
$location = $builder
->create('where')
->addModelTransformer(
new SpecToStringTransformer(Spec\CompanyLocation::class, 'location')
);
$builder
->add($terms)
->add($location);
}
// ...
}
Personally I prefer using a Query passing the data to a Handler. Then the Handler creates the Specifications to pass them to my repository. The Handler then returns the Set from the Collection.
A word on "coupling business logic with the specification pattern":
I can understand that looking at these concrete Doctrine implementations make you think, that business logic is linked to persistence. But coming from a DDD approach you would create a Base Specification like "filterGroup". Then you create a Doctrine (or Mysql, Mongo, InMemory) class based on that Spec and add only the stuff that will be related to the same Persistence storage: DoctrineUserRepository or InMemoryRepository. What you want is the coupling of the Business Logic to the Specification. And then you build your infrastructure around it.
http://www.whitewashing.de/2013/03/04/doctrine_repositories.html#comment-2751511485
I think @timglabisch also prefers this kind of approach? http://www.whitewashing.de/2013/03/04/doctrine_repositories.html#comment-1280738273
Coming from this nice article by @beberlei: http://www.whitewashing.de/2013/03/04/doctrine_repositories.html#comment-2751511485
Which was an inspiration on the @Happyr Doctrine-Specification btw..
There is also an bundle by @rikbruil inspired by @Happyr Doctrine-Specification implementing the Doctrine Paginator: https://github.com/rikbruil/Doctrine-Specification
BTW: Doing my first steps with @Happyr now:
/**
* Class DoctrineContractRepository
*
* @package Rewotec\Contract\Infrastructure\Persistence\Doctrine
*/
class DoctrineContractRepository
extends EntityRepository
implements ContractRepository
{
use EntitySpecificationRepositoryTrait;
Works like a charm @Nyholm!
Testing some more complex stuff now: https://github.com/Happyr/Doctrine-Specification/issues/128
Where do you guys suggest to put the Specifications?
Normally I think they would go into the Domain
/ DomainModel
namespace.
But since the examples are used with Doctrine the are coupled to the infrastructure.
At least they should go into Acme\Infrastructure
.
I've seen people adding a Domain namespace for this:
Thoughts?
There are some nice tutorials out there:
For Zend Framework too by @UFOMelkor:
Another implementation by @mbrevda:
And @maximecolin:
But there is also a implementation for Doctrine by @Happyr @Nyholm @cakper:
Anybody else with other implementations? What are your experiences? Any best practices? Thanks for the feedback!