diff --git a/src/InnerResultIterator.php b/src/InnerResultIterator.php index 24f950f1..e1a0bae0 100644 --- a/src/InnerResultIterator.php +++ b/src/InnerResultIterator.php @@ -241,6 +241,9 @@ public function next(): void $dbRow = $this->objectStorage->get($mainBeanTableName, $hash); if ($dbRow !== null) { $bean = $dbRow->getTDBMObject(); + if ($bean->_getStatus() === TDBMObjectStateEnum::STATE_NOT_LOADED) { + $bean->_constructFromData($beanData, $this->tdbmService); + } } else { // Let's construct the bean if (!isset($reflectionClassCache[$actualClassName])) { diff --git a/tests/Dao/TestCountryDao.php b/tests/Dao/TestCountryDao.php index e2f11a46..ca8779b4 100644 --- a/tests/Dao/TestCountryDao.php +++ b/tests/Dao/TestCountryDao.php @@ -77,4 +77,12 @@ public function getCountriesUsingDistinctQuery() return $this->findFromRawSql($sql); } + + /** + * @return CountryBean[]|Result + */ + public function findByIds(array $ids) + { + return $this->find('id IN (:ids)', ['ids' => $ids]); + } } diff --git a/tests/TDBMDaoGeneratorTest.php b/tests/TDBMDaoGeneratorTest.php index 0e4e920e..9f601f6a 100644 --- a/tests/TDBMDaoGeneratorTest.php +++ b/tests/TDBMDaoGeneratorTest.php @@ -2405,6 +2405,65 @@ public function testPivotTableAreProperlyEscaped(): void $this->assertCount(1, $accessible->getValues()); } + public function testHydrateLazyLoadedBean(): void + { + $countryDao = new TestCountryDao($this->tdbmService); + $country = $countryDao->getById(1, true); + $this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $country->_getStatus()); + $countryDao->findByIds([1])->toArray(); // This `->toArray` consumes the iterator and hence resolves the objects + $this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $country->_getStatus()); + } + + public function testHydrateNotLoadedBeanReference(): void + { + $userDao = new UserDao($this->tdbmService); + $countryDao = new TestCountryDao($this->tdbmService); + $users = $userDao->findAll()->toArray(); + $countriesIds = []; + foreach ($users as $user) { + assert($user instanceof UserBean); + $countriesIds[] = $user->getCountry()->getId(); + $this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $user->getCountry()->_getStatus()); + } + + $countryDao->findByIds($countriesIds)->toArray(); // This `->toArray` consumes the iterator and hence resolves the objects + foreach ($users as $user) { + assert($user instanceof UserBean); + $this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $user->getCountry()->_getStatus()); + } + } + + public function testHydrateNotLoadedBeans(): void + { + $userDao = new UserDao($this->tdbmService); + $countryDao = new TestCountryDao($this->tdbmService); + $users = $userDao->findAll()->toArray(); + $countriesIds = []; + foreach ($users as $user) { + assert($user instanceof UserBean); + $countriesIds[] = $user->getCountry()->getId(); + $this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $user->getCountry()->_getStatus()); + } + + $countries = $countryDao->findByIds($countriesIds); + foreach ($countries as $country) { + assert($country instanceof CountryBean); + $this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $country->_getStatus()); + } + } + + public function testHydrateGetByIdAfterLazyLoad(): void + { + // FIXME: It is not trivial to fix as `\TheCodingMachine\TDBM\TDBMService::findObjectOrFail` creates its own bean. + // Hence, any existing reference to the original bean won't get the change. + $this->markTestIncomplete('Test is failing because we retrieve the bean from the storage and do not hydrate it'); + $countryDao = new TestCountryDao($this->tdbmService); + $country = $countryDao->getById(1, true); + $this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $country->_getStatus()); + $country = $countryDao->getById(1); + $this->assertSame(TDBMObjectStateEnum::STATE_LOADED, $country->_getStatus()); // This is failing + } + private function skipOracle(): void { if (self::getConnection()->getDatabasePlatform() instanceof OraclePlatform) {