Skip to content

Commit

Permalink
Merge pull request #11722 from doctrine/2.20.x
Browse files Browse the repository at this point in the history
Merge 2.20.x up into 2.21.x
  • Loading branch information
greg0ire authored Nov 23, 2024
2 parents a4a15ad + 82e2c98 commit 91201c0
Show file tree
Hide file tree
Showing 12 changed files with 421 additions and 10 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ jobs:
- "default"
- "3@dev"
postgres-version:
- "15"
- "17"
extension:
- pdo_pgsql
- pgsql
Expand Down Expand Up @@ -381,7 +381,7 @@ jobs:
path: "reports"

- name: "Upload to Codecov"
uses: "codecov/codecov-action@v4"
uses: "codecov/codecov-action@v5"
with:
directory: reports
env:
Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/unitofwork.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ How Doctrine Detects Changes
----------------------------

Doctrine is a data-mapper that tries to achieve persistence-ignorance (PI).
This means you map php objects into a relational database that don't
This means you map PHP objects into a relational database that don't
necessarily know about the database at all. A natural question would now be,
"how does Doctrine even detect objects have changed?".

Expand Down
1 change: 1 addition & 0 deletions docs/en/tutorials/extra-lazy-associations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ can be called without triggering a full load of the collection:
- ``Collection#containsKey($key)``
- ``Collection#count()``
- ``Collection#get($key)``
- ``Collection#isEmpty()``
- ``Collection#slice($offset, $length = null)``

For each of the above methods the following semantics apply:
Expand Down
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<referencedClass name="Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand"/>
<referencedClass name="Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper"/>
<referencedClass name="Doctrine\ORM\Tools\Console\EntityManagerProvider\HelperSetManagerProvider"/>
<referencedClass name="Doctrine\Persistence\Mapping\StaticReflectionService"/>
</errorLevel>
</DeprecatedClass>
<DeprecatedConstant>
Expand Down
6 changes: 2 additions & 4 deletions src/Events.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,14 @@ private function __construct()
* The onFlush event occurs when the EntityManager#flush() operation is invoked,
* after any changes to managed entities have been determined but before any
* actual database operations are executed. The event is only raised if there is
* actually something to do for the underlying UnitOfWork. If nothing needs to be done,
* the onFlush event is not raised.
* actually something to do for the underlying UnitOfWork.
*/
public const onFlush = 'onFlush';

/**
* The postFlush event occurs when the EntityManager#flush() operation is invoked and
* after all actual database operations are executed successfully. The event is only raised if there is
* actually something to do for the underlying UnitOfWork. If nothing needs to be done,
* the postFlush event is not raised. The event won't be raised if an error occurs during the
* actually something to do for the underlying UnitOfWork. The event won't be raised if an error occurs during the
* flush operation.
*/
public const postFlush = 'postFlush';
Expand Down
6 changes: 5 additions & 1 deletion src/Persisters/Entity/BasicEntityPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ class BasicEntityPersister implements EntityPersister
/** @var CachedPersisterContext */
private $noLimitsContext;

/** @var ?string */
private $filterHash = null;

/**
* Initializes a new <tt>BasicEntityPersister</tt> that uses the given EntityManager
* and persists instances of the class described by the given ClassMetadata descriptor.
Expand Down Expand Up @@ -1271,7 +1274,7 @@ final protected function getOrderBySQL(array $orderBy, string $baseTableAlias):
*/
protected function getSelectColumnsSQL()
{
if ($this->currentPersisterContext->selectColumnListSql !== null) {
if ($this->currentPersisterContext->selectColumnListSql !== null && $this->filterHash === $this->em->getFilters()->getHash()) {
return $this->currentPersisterContext->selectColumnListSql;
}

Expand Down Expand Up @@ -1378,6 +1381,7 @@ protected function getSelectColumnsSQL()
}

$this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
$this->filterHash = $this->em->getFilters()->getHash();

return $this->currentPersisterContext->selectColumnListSql;
}
Expand Down
4 changes: 2 additions & 2 deletions src/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -2473,13 +2473,13 @@ private function doRefresh($entity, array &$visited, ?int $lockMode = null): voi
throw ORMInvalidArgumentException::entityNotManaged($entity);
}

$this->cascadeRefresh($entity, $visited, $lockMode);

$this->getEntityPersister($class->name)->refresh(
array_combine($class->getIdentifierFieldNames(), $this->entityIdentifiers[$oid]),
$entity,
$lockMode
);

$this->cascadeRefresh($entity, $visited, $lockMode);
}

/**
Expand Down
161 changes: 161 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/LazyEagerCollectionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\Tests\OrmFunctionalTestCase;

class LazyEagerCollectionTest extends OrmFunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();

$this->createSchemaForModels(
LazyEagerCollectionUser::class,
LazyEagerCollectionAddress::class,
LazyEagerCollectionPhone::class
);
}

public function testRefreshRefreshesBothLazyAndEagerCollections(): void
{
$user = new LazyEagerCollectionUser();
$user->data = 'Guilherme';

$ph = new LazyEagerCollectionPhone();
$ph->data = '12345';
$user->addPhone($ph);

$ad = new LazyEagerCollectionAddress();
$ad->data = '6789';
$user->addAddress($ad);

$this->_em->persist($user);
$this->_em->persist($ad);
$this->_em->persist($ph);
$this->_em->flush();
$this->_em->clear();

$user = $this->_em->find(LazyEagerCollectionUser::class, $user->id);
$ph = $user->phones[0];
$ad = $user->addresses[0];

$ph->data = 'abc';
$ad->data = 'def';

$this->_em->refresh($user);

self::assertSame('12345', $ph->data);
self::assertSame('6789', $ad->data);
}
}

/**
* @Entity
*/
class LazyEagerCollectionUser
{
/**
* @var int
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;

/**
* @var string
* @Column(type="string", length=255)
*/
public $data;

/**
* @ORM\OneToMany(targetEntity="LazyEagerCollectionPhone", cascade={"refresh"}, fetch="EAGER", mappedBy="user")
*
* @var LazyEagerCollectionPhone[]
*/
public $phones;

/**
* @ORM\OneToMany(targetEntity="LazyEagerCollectionAddress", cascade={"refresh"}, mappedBy="user")
*
* @var LazyEagerCollectionAddress[]
*/
public $addresses;

public function __construct()
{
$this->addresses = new ArrayCollection();
$this->phones = new ArrayCollection();
}

public function addPhone(LazyEagerCollectionPhone $phone): void
{
$phone->user = $this;
$this->phones[] = $phone;
}

public function addAddress(LazyEagerCollectionAddress $address): void
{
$address->user = $this;
$this->addresses[] = $address;
}
}

/** @Entity */
class LazyEagerCollectionPhone
{
/**
* @var int
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;

/**
* @var string
* @Column(type="string", length=255)
*/
public $data;

/**
* @ORM\ManyToOne(targetEntity="LazyEagerCollectionUser", inversedBy="phones")
*
* @var LazyEagerCollectionUser
*/
public $user;
}

/** @Entity */
class LazyEagerCollectionAddress
{
/**
* @var int
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;

/**
* @var string
* @Column(type="string", length=255)
*/
public $data;

/**
* @ORM\ManyToOne(targetEntity="LazyEagerCollectionUser", inversedBy="addresses")
*
* @var LazyEagerCollectionUser
*/
public $user;
}
Loading

0 comments on commit 91201c0

Please sign in to comment.