1
0
mirror of synced 2025-03-19 22:43:58 +03:00

Merge pull request #706 from sandermarechal/extra-lazy-get

[DDC-1398] Extra-lazy get for indexed associations
This commit is contained in:
Benjamin Eberlei 2013-06-20 05:26:52 -07:00
commit eaf8fd3c34
4 changed files with 145 additions and 6 deletions

View File

@ -517,6 +517,17 @@ final class PersistentCollection implements Collection, Selectable
*/
public function get($key)
{
if ( ! $this->initialized
&& $this->association['fetch'] === Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY
&& isset($this->association['indexBy'])
) {
if (!$this->typeClass->isIdentifierComposite && $this->typeClass->isIdentifier($this->association['indexBy'])) {
return $this->em->find($this->typeClass->name, $key);
}
return $this->em->getUnitOfWork()->getCollectionPersister($this->association)->get($this, $key);
}
$this->initialize();
return $this->coll->get($key);

View File

@ -33,6 +33,24 @@ use Doctrine\ORM\UnitOfWork;
*/
class ManyToManyPersister extends AbstractCollectionPersister
{
/**
* {@inheritdoc}
*
* @override
*/
public function get(PersistentCollection $coll, $index)
{
$mapping = $coll->getMapping();
$uow = $this->em->getUnitOfWork();
$persister = $uow->getEntityPersister($mapping['targetEntity']);
if (!isset($mapping['indexBy'])) {
throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections.");
}
return $persister->load(array($mapping['indexBy'] => $index), null, null, array(), 0, 1);
}
/**
* {@inheritdoc}
*

View File

@ -32,6 +32,24 @@ use Doctrine\ORM\UnitOfWork;
*/
class OneToManyPersister extends AbstractCollectionPersister
{
/**
* {@inheritdoc}
*
* @override
*/
public function get(PersistentCollection $coll, $index)
{
$mapping = $coll->getMapping();
$uow = $this->em->getUnitOfWork();
$persister = $uow->getEntityPersister($mapping['targetEntity']);
if (!isset($mapping['indexBy'])) {
throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections.");
}
return $persister->load(array($mapping['indexBy'] => $index), null, null, array(), 0, 1);
}
/**
* Generates the SQL UPDATE that updates a particular row's foreign
* key to null.

View File

@ -17,6 +17,10 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
private $groupId;
private $articleId;
private $groupname;
private $topic;
private $phonenumber;
public function setUp()
{
$this->useModelSet('cms');
@ -24,7 +28,11 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$class->associationMappings['groups']['indexBy'] = 'name';
$class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$class->associationMappings['articles']['indexBy'] = 'topic';
$class->associationMappings['phonenumbers']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
$class->associationMappings['phonenumbers']['indexBy'] = 'phonenumber';
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_EXTRA_LAZY;
@ -39,6 +47,11 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser');
$class->associationMappings['groups']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
$class->associationMappings['articles']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
$class->associationMappings['phonenumbers']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
unset($class->associationMappings['groups']['indexBy']);
unset($class->associationMappings['articles']['indexBy']);
unset($class->associationMappings['phonenumbers']['indexBy']);
$class = $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsGroup');
$class->associationMappings['users']['fetch'] = ClassMetadataInfo::FETCH_LAZY;
@ -174,8 +187,8 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
$this->assertEquals(2, count($someGroups));
$this->assertTrue($user->groups->contains($someGroups[0]));
$this->assertTrue($user->groups->contains($someGroups[1]));
$this->assertTrue($user->groups->contains(array_shift($someGroups)));
$this->assertTrue($user->groups->contains(array_shift($someGroups)));
}
/**
@ -512,6 +525,72 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals($qc + 1, $this->getCurrentQueryCount());
}
/**
* @group DDC-1398
*/
public function testGetIndexByIdentifier()
{
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
/* @var $user CmsUser */
$queryCount = $this->getCurrentQueryCount();
$phonenumber = $user->phonenumbers->get($this->phonenumber);
$this->assertFalse($user->phonenumbers->isInitialized());
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
$this->assertSame($phonenumber, $this->_em->find('Doctrine\Tests\Models\CMS\CmsPhonenumber', $this->phonenumber));
$article = $user->phonenumbers->get($this->phonenumber);
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount(), "Getting the same entity should not cause an extra query to be executed");
}
/**
* @group DDC-1398
*/
public function testGetIndexByOneToMany()
{
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
/* @var $user CmsUser */
$queryCount = $this->getCurrentQueryCount();
$article = $user->articles->get($this->topic);
$this->assertFalse($user->articles->isInitialized());
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
$this->assertSame($article, $this->_em->find('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId));
}
/**
* @group DDC-1398
*/
public function testGetIndexByManyToMany()
{
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
/* @var $user CmsUser */
$queryCount = $this->getCurrentQueryCount();
$group = $user->groups->get($this->groupname);
$this->assertFalse($user->groups->isInitialized());
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
$this->assertSame($group, $this->_em->find('Doctrine\Tests\Models\CMS\CmsGroup', $this->groupId));
}
/**
* @group DDC-1398
*/
public function testGetNonExistentIndexBy()
{
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $this->userId);
/* @var $user CmsUser */
$this->assertNull($user->articles->get(-1));
$this->assertNull($user->groups->get(-1));
}
private function loadFixture()
{
$user1 = new \Doctrine\Tests\Models\CMS\CmsUser();
@ -561,23 +640,36 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->persist($group3);
$article1 = new \Doctrine\Tests\Models\CMS\CmsArticle();
$article1->topic = "Test";
$article1->text = "Test";
$article1->topic = "Test1";
$article1->text = "Test1";
$article1->setAuthor($user1);
$article2 = new \Doctrine\Tests\Models\CMS\CmsArticle();
$article2->topic = "Test";
$article2->text = "Test";
$article2->topic = "Test2";
$article2->text = "Test2";
$article2->setAuthor($user1);
$this->_em->persist($article1);
$this->_em->persist($article2);
$phonenumber1 = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
$phonenumber1->phonenumber = '12345';
$phonenumber2 = new \Doctrine\Tests\Models\CMS\CmsPhonenumber();
$phonenumber2->phonenumber = '67890';
$this->_em->persist($phonenumber1);
$this->_em->persist($phonenumber2);
$this->_em->flush();
$this->_em->clear();
$this->articleId = $article1->id;
$this->userId = $user1->getId();
$this->groupId = $group1->id;
$this->groupname = $group1->name;
$this->topic = $article1->topic;
$this->phonenumber = $phonenumber1->phonenumber;
}
}