Skip to content

Commit 81791c3

Browse files
committed
⚡ Hydrate not-loaded objects on retrieval
Previously there were a bug (reproduced in tests) where retrieving an already not-loaded object would not hydrate it and hence trigger a new query on access.
1 parent 516ef67 commit 81791c3

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

src/InnerResultIterator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ public function next(): void
241241
$dbRow = $this->objectStorage->get($mainBeanTableName, $hash);
242242
if ($dbRow !== null) {
243243
$bean = $dbRow->getTDBMObject();
244+
if ($bean->_getStatus() === TDBMObjectStateEnum::STATE_NOT_LOADED) {
245+
$bean->_constructFromData($beanData, $this->tdbmService);
246+
}
244247
} else {
245248
// Let's construct the bean
246249
if (!isset($reflectionClassCache[$actualClassName])) {

tests/Dao/TestCountryDao.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,12 @@ public function getCountriesUsingDistinctQuery()
7777

7878
return $this->findFromRawSql($sql);
7979
}
80+
81+
/**
82+
* @return CountryBean[]|Result
83+
*/
84+
public function findByIds(array $ids)
85+
{
86+
return $this->find('id IN (:ids)', ['ids' => $ids]);
87+
}
8088
}

tests/TDBMDaoGeneratorTest.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,6 +2405,65 @@ public function testPivotTableAreProperlyEscaped(): void
24052405
$this->assertCount(1, $accessible->getValues());
24062406
}
24072407

2408+
public function testHydrateLazyLoadedBean(): void
2409+
{
2410+
$countryDao = new TestCountryDao($this->tdbmService);
2411+
$country = $countryDao->getById(1, true);
2412+
$this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $country->_getStatus());
2413+
$countryDao->findByIds([1])->toArray(); // This `->toArray` consumes the iterator and hence resolves the objects
2414+
$this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $country->_getStatus());
2415+
}
2416+
2417+
public function testHydrateNotLoadedBeanReference(): void
2418+
{
2419+
$userDao = new UserDao($this->tdbmService);
2420+
$countryDao = new TestCountryDao($this->tdbmService);
2421+
$users = $userDao->findAll()->toArray();
2422+
$countriesIds = [];
2423+
foreach ($users as $user) {
2424+
assert($user instanceof UserBean);
2425+
$countriesIds[] = $user->getCountry()->getId();
2426+
$this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $user->getCountry()->_getStatus());
2427+
}
2428+
2429+
$countryDao->findByIds($countriesIds)->toArray(); // This `->toArray` consumes the iterator and hence resolves the objects
2430+
foreach ($users as $user) {
2431+
assert($user instanceof UserBean);
2432+
$this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $user->getCountry()->_getStatus());
2433+
}
2434+
}
2435+
2436+
public function testHydrateNotLoadedBeans(): void
2437+
{
2438+
$userDao = new UserDao($this->tdbmService);
2439+
$countryDao = new TestCountryDao($this->tdbmService);
2440+
$users = $userDao->findAll()->toArray();
2441+
$countriesIds = [];
2442+
foreach ($users as $user) {
2443+
assert($user instanceof UserBean);
2444+
$countriesIds[] = $user->getCountry()->getId();
2445+
$this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $user->getCountry()->_getStatus());
2446+
}
2447+
2448+
$countries = $countryDao->findByIds($countriesIds);
2449+
foreach ($countries as $country) {
2450+
assert($country instanceof CountryBean);
2451+
$this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $country->_getStatus());
2452+
}
2453+
}
2454+
2455+
public function testHydrateGetByIdAfterLazyLoad(): void
2456+
{
2457+
// FIXME: It is not trivial to fix as `\TheCodingMachine\TDBM\TDBMService::findObjectOrFail` creates its own bean.
2458+
// Hence, any existing reference to the original bean won't get the change.
2459+
$this->markTestIncomplete('Test is failing because we retrieve the bean from the storage and do not hydrate it');
2460+
$countryDao = new TestCountryDao($this->tdbmService);
2461+
$country = $countryDao->getById(1, true);
2462+
$this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $country->_getStatus());
2463+
$country = $countryDao->getById(1);
2464+
$this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $country->_getStatus()); // This is failing
2465+
}
2466+
24082467
private function skipOracle(): void
24092468
{
24102469
if (self::getConnection()->getDatabasePlatform() instanceof OraclePlatform) {

0 commit comments

Comments
 (0)