Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Proxy/ProxyFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ private function getProxyFactory(string $className): Closure
foreach ($reflector->getProperties($filter) as $property) {
$name = $property->name;

if ($property->isStatic() || (($class->hasField($name) || $class->hasAssociation($name)) && ! isset($identifiers[$name]))) {
if ($property->isStatic() || ! isset($identifiers[$name])) {
continue;
}

Expand Down
62 changes: 62 additions & 0 deletions tests/Tests/Models/Product/Product.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\Product;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
*/
#[ORM\Entity]
class Product
{
/**
* @var int
* @ORM\Id
* @ORM\Column()
* @ORM\GeneratedValue
*/
#[ORM\Id]
#[ORM\Column()]
#[ORM\GeneratedValue]
private $id = 42;

/**
* @var string
* @ORM\Column()
*/
#[ORM\Column()]
private $name;

/**
* @var string|null
*/
private $image = null;

public function __construct(string $name)
{
$this->name = $name;
}

public function getId(): int
{
return $this->id;
}

public function getName(): string
{
return $this->name;
}

public function getImage(): ?string
{
return $this->image;
}

public function setImage(string $image): void
{
$this->image = $image;
}
}
14 changes: 10 additions & 4 deletions tests/Tests/ORM/Functional/LifecycleCallbackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ protected function setUp(): void
{
parent::setUp();

LifecycleCallbackTestEntity::$staticPostLoadCallbackInvoked = false;

$this->createSchemaForModels(
LifecycleCallbackEventArgEntity::class,
LifecycleCallbackTestEntity::class,
Expand Down Expand Up @@ -132,10 +134,10 @@ public function testGetReferenceWithPostLoadEventIsDelayedUntilProxyTrigger(): v
$this->_em->clear();

$reference = $this->_em->getReference(LifecycleCallbackTestEntity::class, $id);
self::assertFalse($reference->postLoadCallbackInvoked);
self::assertFalse(LifecycleCallbackTestEntity::$staticPostLoadCallbackInvoked);

$reference->getValue(); // trigger proxy load
self::assertTrue($reference->postLoadCallbackInvoked);
self::assertTrue(LifecycleCallbackTestEntity::$staticPostLoadCallbackInvoked);
}

/** @group DDC-958 */
Expand Down Expand Up @@ -494,6 +496,9 @@ class LifecycleCallbackTestEntity
/** @var bool */
public $postLoadCallbackInvoked = false;

/** @var bool */
public static $staticPostLoadCallbackInvoked = false;

/** @var bool */
public $postLoadCascaderNotNull = false;

Expand Down Expand Up @@ -546,8 +551,9 @@ public function doStuffOnPostPersist(): void
/** @PostLoad */
public function doStuffOnPostLoad(): void
{
$this->postLoadCallbackInvoked = true;
$this->postLoadCascaderNotNull = isset($this->cascader);
$this->postLoadCallbackInvoked = true;
self::$staticPostLoadCallbackInvoked = true;
$this->postLoadCascaderNotNull = isset($this->cascader);
}

/** @PreUpdate */
Expand Down
36 changes: 36 additions & 0 deletions tests/Tests/ORM/Proxy/ProxyFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Doctrine\Tests\Models\Company\CompanyEmployee;
use Doctrine\Tests\Models\Company\CompanyPerson;
use Doctrine\Tests\Models\ECommerce\ECommerceFeature;
use Doctrine\Tests\Models\Product\Product;
use Doctrine\Tests\OrmTestCase;
use Doctrine\Tests\PHPUnitCompatibility\MockBuilderCompatibilityTools;
use Exception;
Expand Down Expand Up @@ -239,6 +240,41 @@ public function testProxyClonesParentFields(): void
self::assertSame(1000, $cloned->getSalary(), 'Expect properties on the CompanyEmployee class to be cloned');
self::assertSame('Bob', $cloned->getName(), 'Expect properties on the CompanyPerson class to be cloned');
}

public function testUnmanagedPropertyTriggerProxyLoad(): void
{
$product = new Product('someName');
$product->setImage('someImage');
$identifier = ['id' => 42];

$classMetaData = $this->emMock->getClassMetadata(Product::class);

$persister = $this
->getMockBuilder(BasicEntityPersister::class)
->disableOriginalConstructor()
->getMock();

$this->uowMock->setEntityPersister(Product::class, $persister);

$persister
->expects(self::atLeastOnce())
->method('loadById')
->with(self::equalTo($identifier))
->willReturn($product);

$persister
->expects(self::atLeastOnce())
->method('getClassMetadata')
->willReturn($classMetaData);

$proxy = $this->proxyFactory->getProxy(Product::class, $identifier);

self::assertFalse($proxy->__isInitialized());
$proxy->getId();
self::assertFalse($proxy->__isInitialized());
$proxy->getImage();
self::assertTrue($proxy->__isInitialized());
}
}

abstract class AbstractClass
Expand Down