1
0
mirror of synced 2025-03-17 13:33:52 +03:00

Merge branch 'DDC-2430'

This commit is contained in:
Benjamin Eberlei 2013-05-09 13:24:45 +02:00
commit 30f90a6f49
7 changed files with 90 additions and 11 deletions

View File

@ -28,6 +28,20 @@ Now parenthesis are considered, the previous DQL will generate:
SELECT 100 / (2 * 2) FROM my_entity
## Compatibility Bugfix in PersistentCollection#matching() breaks BC
In Doctrine 2.3 it was possible to use the new ``matching($criteria)``
functionality by adding constraints for assocations based on ID:
Criteria::expr()->eq('association', $assocation->getId());
This functionality does not work on InMemory collections however, because
in memory criteria compares object values based on reference.
As of 2.4 the above code will throw an exception. You need to change
offending code to pass the ``$assocation`` reference directly:
Criteria::expr()->eq('association', $assocation);
# Upgrade to 2.3
## EntityManager#find() not calls EntityRepository#find() anymore

View File

@ -850,12 +850,8 @@ final class PersistentCollection implements Collection, Selectable
throw new \RuntimeException("Matching Criteria on PersistentCollection only works on OneToMany associations at the moment.");
}
$id = $this->em
->getClassMetadata(get_class($this->owner))
->getSingleIdReflectionProperty()
->getValue($this->owner);
$builder = Criteria::expr();
$ownerExpression = $builder->eq($this->backRefFieldName, $id);
$ownerExpression = $builder->eq($this->backRefFieldName, $this->owner);
$expression = $criteria->getWhereExpression();
$expression = $expression ? $builder->andX($expression, $ownerExpression) : $ownerExpression;

View File

@ -1583,7 +1583,7 @@ class BasicEntityPersister
return '';
}
$visitor = new SqlExpressionVisitor($this);
$visitor = new SqlExpressionVisitor($this, $this->class);
return $visitor->dispatch($expression);
}

View File

@ -0,0 +1,20 @@
<?php
namespace Doctrine\ORM\Persisters;
use Doctrine\ORM\ORMException;
class PersisterException extends ORMException
{
/**
* @return PersisterException
*/
static public function matchingAssocationFieldRequiresObject($class, $associationName)
{
return new self(sprintf(
"Cannot match on %s::%s with a non-object value. Matching objects by id is " .
"not compatible with matching on an in-memory collection, which compares objects by reference.",
$class, $associationName
));
}
}

View File

@ -19,6 +19,8 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\Common\Collections\Expr\ExpressionVisitor;
use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\Common\Collections\Expr\Value;
@ -37,12 +39,18 @@ class SqlExpressionVisitor extends ExpressionVisitor
*/
private $persister;
/**
* @var \Doctrine\ORM\Mapping\ClassMetadata
*/
private $classMetadata;
/**
* @param \Doctrine\ORM\Persisters\BasicEntityPersister $persister
*/
public function __construct(BasicEntityPersister $persister)
public function __construct(BasicEntityPersister $persister, ClassMetadata $classMetadata)
{
$this->persister = $persister;
$this->classMetadata = $classMetadata;
}
/**
@ -57,6 +65,10 @@ class SqlExpressionVisitor extends ExpressionVisitor
$field = $comparison->getField();
$value = $comparison->getValue()->getValue(); // shortcut for walkValue()
if (isset($this->classMetadata->associationMappings[$field]) && ! is_object($value)) {
throw PersisterException::matchingAssocationFieldRequiresObject($this->classMetadata->name, $field);
}
return $this->persister->getSelectConditionStatementSQL($field, $value, null, $comparison->getOperator());
}

View File

@ -7,8 +7,7 @@ use Doctrine\Tests\Models\CMS\CmsEmail;
use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Common\Collections\Criteria;
require_once __DIR__ . '/../../TestInit.php';
use Doctrine\Common\Collections\ArrayCollection;
/**
* @author robo
@ -781,6 +780,29 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(4, count($users));
}
/**
* @group DDC-2430
*/
public function testMatchingCriteriaAssocationByObjectInMemory()
{
list($userId, $addressId) = $this->loadAssociatedFixture();
$user = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $userId);
$criteria = new Criteria(
Criteria::expr()->gte('user', $user)
);
$repository = $this->_em->getRepository('Doctrine\Tests\Models\CMS\CmsAddress');
$addresses = $repository->matching($criteria);
$this->assertEquals(1, count($addresses));
$addresses = new ArrayCollection($repository->findAll());
$this->assertEquals(1, count($addresses->matching($criteria)));
}
public function testMatchingCriteriaContainsComparison()
{
$this->loadFixture();

View File

@ -343,17 +343,32 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$repository = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyContract");
$contracts = $repository->matching(new Criteria(
Criteria::expr()->eq('salesPerson', $this->salesPerson->getId())
Criteria::expr()->eq('salesPerson', $this->salesPerson)
));
$this->assertEquals(3, count($contracts));
$repository = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFixContract");
$contracts = $repository->matching(new Criteria(
Criteria::expr()->eq('salesPerson', $this->salesPerson->getId())
Criteria::expr()->eq('salesPerson', $this->salesPerson)
));
$this->assertEquals(1, count($contracts));
}
/**
* @group DDC-2430
*/
public function testMatchingNonObjectOnAssocationThrowsException()
{
$this->loadFullFixture();
$repository = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyContract");
$this->setExpectedException('Doctrine\ORM\Persisters\PersisterException', 'annot match on Doctrine\Tests\Models\Company\CompanyContract::salesPerson with a non-object value.');
$contracts = $repository->matching(new Criteria(
Criteria::expr()->eq('salesPerson', $this->salesPerson->getId())
));
}
/**
* @group DDC-834
*/