Skip to content

Commit 646ae97

Browse files
committed
bug #316 Skip embedded fields in embeddables (cedricziel)
This PR was squashed before being merged into the 1.0-dev branch (closes #316). Discussion ---------- Skip embedded fields in embeddables This change skips the creation of mapped fields inside embeddables. Consider the PHP Money class: ```php public class Invoice { /** * @var Money * * @Orm\Embedded(class="Money\Money") */ private $total; } ``` ```php final class Money implements \JsonSerializable { /** * @var Currency */ private $currency; } ``` Here, Money has the mapped field `Currency`. In doctrine Metadata, this is correctly reflected as `total.currency`. The EntityRegenerator declares a private field `$total.currency` afterwards. The changeset suppresses this behaviour by skipping fields containing a dot as is done a few lines below. Commits ------- a4d4787 Embed money objects 074f836 Remove double slash 6b9f7d8 Map embeddable money test with XML for convenience 84e2f58 Add small test to embeddable test 5c48add Skip embedded fields in embeddables
2 parents c99fe21 + a4d4787 commit 646ae97

File tree

6 files changed

+163
-0
lines changed

6 files changed

+163
-0
lines changed

src/Doctrine/EntityRegenerator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ public function regenerateEntities(string $classOrNamespace)
7676
$embeddedClasses = [];
7777

7878
foreach ($classMetadata->embeddedClasses as $fieldName => $mapping) {
79+
if (false !== strpos($fieldName, '.')) {
80+
continue;
81+
}
82+
7983
$className = $mapping['class'];
8084

8185
$embeddedClasses[$fieldName] = $this->getPathOfClass($className);

tests/Maker/FunctionalTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,18 @@ public function getCommandEntityTests()
11361136
->setRequiredPhpVersion(70100)
11371137
];
11381138

1139+
yield 'entity_regenerate_embeddable_object' => [MakerTestDetails::createTest(
1140+
$this->getMakerInstance(MakeEntity::class),
1141+
[
1142+
// namespace: use default App\Entity
1143+
'',
1144+
])
1145+
->setArgumentsString('--regenerate')
1146+
->setFixtureFilesPath(__DIR__.'/../fixtures/MakeEntityRegenerateEmbeddableObject')
1147+
->configureDatabase()
1148+
->setRequiredPhpVersion(70100)
1149+
];
1150+
11391151
yield 'entity_regenerate_embeddable' => [MakerTestDetails::createTest(
11401152
$this->getMakerInstance(MakeEntity::class),
11411153
[
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace App\Entity;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Embeddable()
9+
*/
10+
class Currency
11+
{
12+
/**
13+
* @var string
14+
*
15+
* @ORM\Column(name="currency", type="string")
16+
*/
17+
private $currency;
18+
19+
public function __construct($currency)
20+
{
21+
$this->currency = $currency;
22+
}
23+
24+
/**
25+
* @return string
26+
*/
27+
public function getCurrency()
28+
{
29+
return $this->currency;
30+
}
31+
32+
/**
33+
* @param string $currency
34+
* @return Currency
35+
*/
36+
public function setCurrency($currency)
37+
{
38+
$this->currency = $currency;
39+
return $this;
40+
}
41+
42+
43+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Entity;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Entity()
9+
*/
10+
class Invoice
11+
{
12+
/**
13+
* @ORM\Column(name="id", type="integer")
14+
* @ORM\Id
15+
* @ORM\GeneratedValue(strategy="AUTO")
16+
*/
17+
private $id;
18+
19+
/**
20+
* @ORM\Column(name="title", type="string", length=255)
21+
*/
22+
private $title;
23+
24+
/**
25+
* @ORM\Embedded(class="App\Entity\Money")
26+
*/
27+
private $total;
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Entity;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
class Money
8+
{
9+
/**
10+
* @var Currency
11+
*
12+
* @ORM\Embedded(class="App\Entity\Currency")
13+
*/
14+
private $currency;
15+
16+
/**
17+
* @var int
18+
*
19+
* @ORM\Column(name="amount", type="integer")
20+
*/
21+
private $amount;
22+
23+
public function __construct($amount, Currency $currency)
24+
{
25+
$this->amount = $amount;
26+
$this->currency = $currency;
27+
}
28+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace App\Tests;
4+
5+
use App\Entity\Invoice;
6+
use Money\Currency;
7+
use Money\Money;
8+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
9+
use Doctrine\ORM\EntityManager;
10+
11+
class GeneratedEntityTest extends KernelTestCase
12+
{
13+
public function testGeneratedEntity()
14+
{
15+
self::bootKernel();
16+
/** @var EntityManager $em */
17+
$em = self::$kernel->getContainer()
18+
->get('doctrine')
19+
->getManager();
20+
21+
$em->createQuery('DELETE FROM App\\Entity\\Invoice i')->execute();
22+
23+
$invoice = new Invoice();
24+
// check that the constructor was instantiated properly
25+
$this->assertInstanceOf(Money::class, $invoice->getTotal());
26+
// fields should now have setters
27+
$invoice->setTitle('Borscht');
28+
29+
$total = new Money(100, new Currency('EUR'));
30+
$invoice->setTotal($total);
31+
32+
$em->persist($invoice);
33+
34+
$em->flush();
35+
$em->refresh($invoice);
36+
37+
/** @var Invoice[] $actualInvoice */
38+
$actualInvoice = $em->getRepository(Invoice::class)
39+
->findAll();
40+
41+
$this->assertcount(1, $actualInvoice);
42+
43+
/** @var Money $actualTotal */
44+
$actualTotal = $actualInvoice[0]->getTotal();
45+
46+
$this->assertInstanceOf(Money::class, $actualTotal);
47+
}
48+
}

0 commit comments

Comments
 (0)