diff --git a/src/Hydrators/PrestyledAssoc.php b/src/Hydrators/PrestyledAssoc.php index f83dc2d..28cc0b5 100644 --- a/src/Hydrators/PrestyledAssoc.php +++ b/src/Hydrators/PrestyledAssoc.php @@ -11,6 +11,7 @@ use function explode; use function is_array; +use function strtolower; /** * Hydrates associative rows whose keys are pre-styled as `specifier__styledProp`. @@ -41,7 +42,7 @@ public function hydrateAll( $grouped = []; foreach ($raw as $alias => $value) { [$prefix, $prop] = explode('__', $alias, 2); - $grouped[$prefix][$prop] = $value; + $grouped[strtolower($prefix)][$prop] = $value; } /** @var SplObjectStorage $entities */ @@ -83,9 +84,13 @@ private function buildScopeMap(Scope $scope): array return $this->scopeMap; } + // Keys are lowercased: a column specifier survives the round-trip through + // the database as the alias case the driver chose (PostgreSQL folds + // unquoted identifiers to lower case, others preserve them), so the + // prefix is matched case-insensitively. $this->scopeMap = []; foreach (ScopeIterator::recursive($scope) as $spec => $c) { - $this->scopeMap[$spec] = $c; + $this->scopeMap[strtolower($spec)] = $c; } $this->cachedScope = $scope; diff --git a/tests/Hydrators/PrestyledAssocTest.php b/tests/Hydrators/PrestyledAssocTest.php index e729735..8cbd991 100644 --- a/tests/Hydrators/PrestyledAssocTest.php +++ b/tests/Hydrators/PrestyledAssocTest.php @@ -53,6 +53,26 @@ public function hydrateSingleEntity(): void $this->assertEquals('Alice', $this->factory->get($entity, 'name')); } + #[Test] + public function hydrateMatchesSpecifierPrefixCaseInsensitively(): void + { + // A camelCase scope name (`edgeCaseEntity`) becomes the column specifier; + // PostgreSQL folds the unquoted alias to lower case, so the row comes back + // prefixed `edgecaseentity__`. The prefix must still resolve to its scope. + $hydrator = new PrestyledAssoc($this->factory); + $scope = new Scope('edgeCaseEntity'); + + $result = $hydrator->hydrateAll( + ['edgecaseentity__initialized' => 'folded'], + $scope, + ); + + $this->assertNotFalse($result); + $this->assertCount(1, $result); + $result->rewind(); + $this->assertEquals('folded', $this->factory->get($result->current(), 'initialized')); + } + #[Test] public function hydrateMultipleEntitiesFromJoinedRow(): void {