Skip to content

Commit ed99a2b

Browse files
committed
Replace FlatNum with PrestyledAssoc, use aliased SELECT columns
Switch from FETCH_NUM + getColumnMeta() to FETCH_ASSOC with explicit aliased columns (e.g. post.id AS post__id). The hydrator now parses alias keys directly, removing the PDO driver dependency. buildSelectStatement() uses EntityFactory::enumerateFields() to emit per-column aliases, and Composite::COMPOSITION_MARKER for join prefixes.
1 parent 14a84de commit ed99a2b

3 files changed

Lines changed: 33 additions & 206 deletions

File tree

src/Hydrators/FlatNum.php

Lines changed: 0 additions & 55 deletions
This file was deleted.

src/Mapper.php

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@
1414
use Respect\Data\Collections\Filtered;
1515
use Respect\Data\EntityFactory;
1616
use Respect\Data\Hydrator;
17-
use Respect\Relational\Hydrators\FlatNum;
17+
use Respect\Data\Hydrators\PrestyledAssoc;
1818
use SplObjectStorage;
1919
use Throwable;
2020

2121
use function array_keys;
22-
use function array_merge;
2322
use function array_push;
2423
use function array_values;
2524
use function is_array;
@@ -32,8 +31,6 @@ final class Mapper extends AbstractMapper
3231
{
3332
public readonly Db $db;
3433

35-
private PDOStatement $lastStatement;
36-
3734
/** @var SplObjectStorage<object, true> */
3835
private SplObjectStorage $persisting;
3936

@@ -133,7 +130,7 @@ public function flush(): void
133130

134131
protected function defaultHydrator(Collection $collection): Hydrator
135132
{
136-
return new FlatNum($this->lastStatement);
133+
return new PrestyledAssoc();
137134
}
138135

139136
/** Resolve related entity from relation property or FK field */
@@ -374,48 +371,52 @@ private function buildSelectStatement(Sql $sql, array $collections): Sql
374371
{
375372
$selectTable = [];
376373
foreach ($collections as $tableSpecifier => $c) {
377-
if ($c instanceof Composite) {
378-
foreach ($c->compositions as $composition => $columns) {
379-
foreach ($columns as $col) {
380-
$selectTable[] = $tableSpecifier . '_comp' . $composition . '.' . $col;
381-
}
382-
}
383-
}
384-
385374
if ($c instanceof Filtered) {
386375
$filters = $c->filters;
387376
if ($filters) {
388-
$pkName = $tableSpecifier . '.' .
389-
$this->style->identifier($c->name);
390-
391-
if ($c->identifierOnly) {
392-
$selectColumns = [$pkName];
393-
} else {
394-
$selectColumns = [
395-
$tableSpecifier . '.' .
396-
$this->style->identifier($c->name),
397-
];
377+
$fields = $this->entityFactory->enumerateFields($c->name);
378+
$pk = $this->style->identifier($c->name);
379+
$selectTable[] = self::aliasedColumn($tableSpecifier, $pk, $fields[$pk] ?? $pk);
380+
381+
if (!$c->identifierOnly) {
398382
foreach ($filters as $f) {
399-
$selectColumns[] = $tableSpecifier . '.' . $f;
383+
$selectTable[] = self::aliasedColumn($tableSpecifier, $f, $fields[$f] ?? $f);
400384
}
401385
}
402386

403387
$nextName = $c->next?->name;
404388
if ($nextName !== null) {
405-
$selectColumns[] = $tableSpecifier . '.' .
406-
$this->style->remoteIdentifier($nextName);
389+
$fk = $this->style->remoteIdentifier($nextName);
390+
$selectTable[] = self::aliasedColumn($tableSpecifier, $fk, $fields[$fk] ?? $fk);
407391
}
408-
409-
$selectTable = array_merge($selectTable, $selectColumns);
410392
}
411393
} else {
412-
$selectTable[] = $tableSpecifier . '.*';
394+
foreach ($this->entityFactory->enumerateFields($c->name) as $dbCol => $styledProp) {
395+
$selectTable[] = self::aliasedColumn($tableSpecifier, $dbCol, $styledProp);
396+
}
397+
}
398+
399+
// Composition columns come after entity columns so they override on collision
400+
if (!$c instanceof Composite) {
401+
continue;
402+
}
403+
404+
foreach ($c->compositions as $composition => $columns) {
405+
$compPrefix = $tableSpecifier . Composite::COMPOSITION_MARKER . $composition;
406+
foreach ($columns as $col) {
407+
$selectTable[] = self::aliasedColumn($compPrefix, $col, $col);
408+
}
413409
}
414410
}
415411

416412
return $sql->select(...$selectTable);
417413
}
418414

415+
private static function aliasedColumn(string $specifier, string $dbCol, string $prop): string
416+
{
417+
return $specifier . '.' . $dbCol . ' AS ' . $specifier . '__' . $prop;
418+
}
419+
419420
/** @param array<string, Collection> $collections */
420421
private function buildTables(Sql $sql, array $collections): Sql
421422
{
@@ -466,7 +467,7 @@ private function parseCompositions(Sql $sql, Collection $collection, string $ent
466467
}
467468

468469
foreach (array_keys($collection->compositions) as $comp) {
469-
$alias = $entity . '_comp' . $comp;
470+
$alias = $entity . Composite::COMPOSITION_MARKER . $comp;
470471
$sql->innerJoin($comp);
471472
$sql->as($alias);
472473
$sql->on([
@@ -569,9 +570,8 @@ private function parseHydrated(SplObjectStorage $hydrated): object
569570
/** @return SplObjectStorage<object, Collection>|false */
570571
private function fetchHydrated(Collection $collection, PDOStatement $statement): SplObjectStorage|false
571572
{
572-
$this->lastStatement = $statement;
573573
$hydrator = $this->resolveHydrator($collection);
574-
$row = $statement->fetch(PDO::FETCH_NUM);
574+
$row = $statement->fetch(PDO::FETCH_ASSOC);
575575

576576
return $hydrator->hydrate($row, $collection, $this->entityFactory);
577577
}
@@ -586,7 +586,7 @@ private function createStatement(
586586
$query->concat($withExtra);
587587
}
588588

589-
$statement = $this->db->prepare((string) $query, PDO::FETCH_NUM);
589+
$statement = $this->db->prepare((string) $query, PDO::FETCH_ASSOC);
590590
$statement->execute($query->params);
591591

592592
return $statement;

tests/Hydrators/FlatNumTest.php

Lines changed: 0 additions & 118 deletions
This file was deleted.

0 commit comments

Comments
 (0)