1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\OrmFunctionalTestCase;
use PHPUnit\Framework\Attributes\Group;
/**
* FlushEventTest
*/
class FlushEventTest extends OrmFunctionalTestCase
{
protected function setUp(): void
{
$this->useModelSet('cms');
parent::setUp();
}
public function testPersistNewEntitiesOnPreFlush(): void
{
$this->_em->getEventManager()->addEventListener(Events::onFlush, new OnFlushListener());
$user = new CmsUser();
$user->username = 'romanb';
$user->name = 'Roman';
$user->status = 'Dev';
$this->_em->persist($user);
self::assertEquals(0, $user->phonenumbers->count());
$this->_em->flush();
self::assertEquals(1, $user->phonenumbers->count());
self::assertTrue($this->_em->contains($user->phonenumbers->get(0)));
self::assertSame($user->phonenumbers->get(0)->getUser(), $user);
self::assertFalse($user->phonenumbers->isDirty());
// Can be used together with SQL Logging to check that a subsequent flush has
// nothing to do. This proofs the correctness of the changes that happened in onFlush.
//echo "SECOND FLUSH";
//$this->_em->flush();
}
#[Group('DDC-2173')]
public function testPreAndOnFlushCalledAlways(): void
{
$listener = new OnFlushCalledListener();
$this->_em->getEventManager()->addEventListener(Events::onFlush, $listener);
$this->_em->getEventManager()->addEventListener(Events::preFlush, $listener);
$this->_em->getEventManager()->addEventListener(Events::postFlush, $listener);
$this->_em->flush();
self::assertEquals(1, $listener->preFlush);
self::assertEquals(1, $listener->onFlush);
$this->_em->flush();
self::assertEquals(2, $listener->preFlush);
self::assertEquals(2, $listener->onFlush);
}
}
class OnFlushListener
{
public function onFlush(OnFlushEventArgs $args): void
{
//echo "---preFlush".PHP_EOL;
$em = $args->getObjectManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityInsertions() as $entity) {
if ($entity instanceof CmsUser) {
// Adds a phonenumber to every newly persisted CmsUser ...
$phone = new CmsPhonenumber();
$phone->phonenumber = 12345;
// Update object model
$entity->addPhonenumber($phone);
// Invoke regular persist call
$em->persist($phone);
// Explicitly calculate the changeset since onFlush is raised
// after changeset calculation!
$uow->computeChangeSet($em->getClassMetadata($phone::class), $phone);
// Take a snapshot because the UoW wont do this for us, because
// the UoW did not visit this collection.
// Alternatively we could provide an ->addVisitedCollection() method
// on the UoW.
$entity->getPhonenumbers()->takeSnapshot();
}
/*foreach ($uow->getEntityChangeSet($entity) as $field => $change) {
list ($old, $new) = $change;
var_dump($old);
}*/
}
}
}
class OnFlushCalledListener
{
/** @var int */
public $preFlush = 0;
/** @var int */
public $onFlush = 0;
/** @var int */
public $postFlush = 0;
public function preFlush($args): void
{
$this->preFlush++;
}
public function onFlush($args): void
{
$this->onFlush++;
}
public function postFlush($args): void
{
$this->postFlush++;
}
}
|