bug #16826 Embedded identifier support (mihai-stancu)

This PR was submitted for the 2.8 branch but it was merged into the 2.3 branch instead (closes #16826).

Discussion
----------

Embedded identifier support

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | none
| License       | MIT
| Doc PR        | n/a

If you define your entity identifier using an embeddable class the identifier name will contain period symbols in it such as `id.value` which will generate a syntax error in the DQL lexer because parameter names are not allowed to contain period symbols.

Example to reproduce described bug:

```php
/**
 * @ORM\Embeddable
 */
class Identifier {
    /**
     * @ORM\Column(type="integer")
     */
    protected $value;
}

/**
 * @ORM\Entity
 */
class Entity {
    /**
     * @ORM\Id @ORM\Embedded(class="Identifier")
     */
    protected $id;
}
```

Commits
-------

38fdda6 Embedded identifier support
This commit is contained in:
Fabien Potencier 2015-12-26 13:11:49 +01:00
commit 021ab8a7b3
4 changed files with 91 additions and 0 deletions

View File

@ -79,6 +79,7 @@ class ORMQueryBuilderLoader implements EntityLoaderInterface
$qb = clone $this->queryBuilder;
$alias = current($qb->getRootAliases());
$parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier;
$parameter = str_replace('.', '_', $parameter);
$where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter);
// Guess type

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\Doctrine\Tests\Fixtures\Embeddable;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Embeddable
*/
class Identifier
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $value;
}

View File

@ -0,0 +1,27 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\Doctrine\Tests\Fixtures;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class EmbeddedIdentifierEntity
{
/**
* @var Embeddable\Identifier
*
* @ORM\Embedded(class="Symfony\Bridge\Doctrine\Tests\Fixtures\Embeddable\Identifier")
*/
protected $id;
}

View File

@ -14,6 +14,7 @@ namespace Symfony\Bridge\Doctrine\Tests\Form\ChoiceList;
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\Version;
class ORMQueryBuilderLoaderTest extends \PHPUnit_Framework_TestCase
{
@ -103,4 +104,38 @@ class ORMQueryBuilderLoaderTest extends \PHPUnit_Framework_TestCase
$loader = new ORMQueryBuilderLoader($qb);
$loader->getEntitiesByIds('id', array(1, '', 2, 3, 'foo'));
}
public function testEmbeddedIdentifierName()
{
if (Version::compare('2.5.0') > 0) {
$this->markTestSkipped('Applicable only for Doctrine >= 2.5.0');
return;
}
$em = DoctrineTestHelper::createTestEntityManager();
$query = $this->getMockBuilder('QueryMock')
->setMethods(array('setParameter', 'getResult', 'getSql', '_doExecute'))
->getMock();
$query->expects($this->once())
->method('setParameter')
->with('ORMQueryBuilderLoader_getEntitiesByIds_id_value', array(1, 2, 3), Connection::PARAM_INT_ARRAY)
->willReturn($query);
$qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
->setConstructorArgs(array($em))
->setMethods(array('getQuery'))
->getMock();
$qb->expects($this->once())
->method('getQuery')
->willReturn($query);
$qb->select('e')
->from('Symfony\Bridge\Doctrine\Tests\Fixtures\EmbeddedIdentifierEntity', 'e');
$loader = new ORMQueryBuilderLoader($qb);
$loader->getEntitiesByIds('id.value', array(1, '', 2, 3, 'foo'));
}
}