Skip to content

steevanb/doctrine-entity-merger

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 

version doctrine php Lines Total Downloads SensionLabsInsight Scrutinizer

doctrine-entity-merger

When you use PARTIAL in DQL, you retrive only fields you need, instead of all Entity fields.

But, if you execute 2 PARTIAL on same entity, but not same fields, you will have this problem :

class FooEntity
{
    protected $id;
    protected $name;
    protected $description;
}

$foo1 = $repository
    ->createQueryBuilder('foo')
    ->select('PARTIAL foo.{id, name}')
    ->where('site.id = 1')
    ->getQuery()
    ->getSingleResult();

var_dump($foo1->getDescription()); // null, that's fine, description is not in PARTIAL

$foo2 = $repository
    ->createQueryBuilder('foo')
    ->select('PARTIAL foo.{id, name, description}')
    ->where('site.id = 1')
    ->getQuery()
    ->getSingleResult();

// $foo1 is same object as $foo2, cause Doctrine know first query hydrated $foo1
// so, when you ask same entity (same id in query) with 2nd query, Doctrine will execute SQL,
// but will not hydrate a new entity
// UnitOfWork will return instance of Foo who is already hydrated, with first query
var_dump(spl_object_hash($foo1) === spl_object_hash($foo2)); // true

// but, as Doctrine return $foo1 in 2nd query, your new field description will not be defined in $foo1
var_dump($foo1->getDescription()); // null, but we want it, cause it's defined in PARTIAL 2nd query

You can use steevanb\DoctrineEntityMerger\QueryHint::MERGE_ENTITY to define description in $foo1 :

use steevanb\DoctrineEntityMerger\QueryHint;

$foo1 = $repository
    ->createQueryBuilder('foo')
    ->select('PARTIAL foo.{id, name}')
    ->where('site.id = 1')
    ->getQuery()
    ->getSingleResult();

var_dump($foo1->getName()); // 'My name' for example
var_dump($foo1->getDescription()); // null, that's fine, description is not in PARTIAL

$foo1->setName('New name');
var_dump($foo1->getName()); // 'New name'

$foo2 = $repository
    ->createQueryBuilder('foo')
    ->select('PARTIAL foo.{id, description}')
    ->where('site.id = 1')
    ->getQuery()
    ->setHint(QueryHint::MERGE_ENTITY, true)
    ->getSingleResult();

var_dump($foo1->getName()); // 'New name', MERGE_ENTITY will not change Foo::$name value if it was already defined in another query before

var_dump($foo1->getDescription()); // 'My description'

Changelog

Installation

As doctrine-entity-merger use steevanb/doctrine-events, see how to install it (composer dependecy is added here, you don't need to add it for steevanb/doctrine-events) :

steevanb/doctrine-events

Add it to your composer.json :

{
    "require": {
        "steevanb/doctrine-entity-merger": "^1.0.5",
    }
}

Add EntityMergerSubscriber :

$entityManager->getEventManager()->addEventSubscriber(
    new steevanb\DoctrineEntityMerger\EventSubscriber\EntityMergerSubscriber()
);

If you want to add MERGE_ENTITY hint to all of your queries, you can do this :

$entityManager->getConfiguration()->setDefaultQueryHint(
    steevanb\DoctrineEntityMerger\QueryHint\QueryHint::MERGE_ENTITY,
    true
);

For example, if you are on a Symfony project, you can add it in AppKernel :

# app/AppKernel.php

use Doctrine\ORM\EntityManagerInterface;
use steevanb\DoctrineEntityMerger\QueryHint;
use steevanb\DoctrineEntityMerger\EventSubscriber\EntityMergerSubscriber;

class AppKernel
{
    public function boot()
    {
        parent::boot();
        
        foreach ($this->getContainer()->get('doctrine')->getManagers() as $manager) {
            if ($manager instanceof EntityManagerInterface) {
                // add hint MERGE_ENTITY to all your queries
                $manager->getConfiguration()->setDefaultQueryHint(QueryHint::MERGE_ENTITY, true);

                // add listener, who use steevanb/doctrine-events to change UnitOfWork::createEntity()
                // to take into account MERGE_ENTITY hint
                $manager->getEventManager()->addEventSubscriber(new EntityMergerSubscriber());
            }
        }
    }
}

About

Add hint MERGE_ENTITY to merge fields retrieved by many queries

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages