From a68f501d2b64ee7be4bc204a99badc9b6c2d52ce Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 11 Jan 2024 16:39:12 +0100 Subject: [PATCH] Hydrator: Correctly hydrate custom aliases targeting targets with underscores in their name fixes #125 --- src/Hydrator.php | 21 ++++++++++++++------- tests/HydratorTest.php | 41 +++++++++++++++++++++++++++++++++++++++++ tests/User.php | 3 +++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/Hydrator.php b/src/Hydrator.php index c4797e4..ef7730e 100644 --- a/src/Hydrator.php +++ b/src/Hydrator.php @@ -154,23 +154,30 @@ public function hydrate(array $data, Model $model) $columnName = $column; $steps = explode('_', $column); $baseTable = array_shift($steps); + while (! empty($steps) && $baseTable !== $model->getTableAlias()) { + $baseTable .= '_' . array_shift($steps); + } $subject = $model; $target = $this->query->getModel(); $stepsTaken = []; - foreach ($steps as $step) { + for ($i = 0; $i < count($steps); $i++) { + $step = $steps[$i]; $stepsTaken[] = $step; $relationPath = "$baseTable." . implode('.', $stepsTaken); try { $relation = $this->query->getResolver()->resolveRelation($relationPath); - } catch (InvalidArgumentException $_) { - // The base table is missing, which means the alias hasn't been qualified and is custom defined - break; } catch (InvalidRelationException $_) { - array_pop($stepsTaken); - $columnName = implode('_', array_slice($steps, count($stepsTaken))); - break; + if (isset($steps[$i + 1])) { + $steps[$i + 1] = $step . '_' . $steps[$i + 1]; + array_pop($stepsTaken); + continue; + } else { + array_pop($stepsTaken); + $columnName = implode('_', array_slice($steps, $i)); + break; + } } if (! $subject->hasProperty($step)) { diff --git a/tests/HydratorTest.php b/tests/HydratorTest.php index 0bd6bc2..cbcfe6c 100644 --- a/tests/HydratorTest.php +++ b/tests/HydratorTest.php @@ -46,4 +46,45 @@ public function testWhetherProperlyQualifiedColumnsAreOnlyPassedOnToMatchingTarg 'Properly qualified relation columns are spilled onto the base model' ); } + + public function testCustomAliasesForTheBaseTableAndRelationsWithUnderscoresInTheirNameAreProperlyHydrated() + { + $query = CarUser::on(new TestConnection()) + ->with('user'); + + $hydrator = $query->createHydrator(); + + $subject = new CarUser(); + $hydrator->hydrate(['car_user_definitely' => 'custom'], $subject); + + $this->assertTrue( + isset($subject->definitely), + 'Custom aliases for the base table are not correctly' + . ' hydrated if the table name contains an underscore' + ); + $this->assertSame( + 'custom', + $subject->definitely, + 'Custom aliases for the base table are not correctly' + . ' hydrated if the table name contains an underscore' + ); + + $query = User::on(new TestConnection()) + ->with('user_custom_keys'); + + $hydrator = $query->createHydrator(); + + $subject = new User(); + $hydrator->hydrate(['user_user_custom_keys_definitely' => 'custom'], $subject); + + $this->assertTrue( + isset($subject->user_custom_keys->definitely), + 'Custom aliases for relations are not correctly hydrated if their name contains an underscore' + ); + $this->assertSame( + 'custom', + $subject->user_custom_keys->definitely, + 'Custom aliases for relations are not correctly hydrated if their name contains an underscore' + ); + } } diff --git a/tests/User.php b/tests/User.php index afcbf3a..20e33ec 100644 --- a/tests/User.php +++ b/tests/User.php @@ -38,5 +38,8 @@ public function createRelations(Relations $relations) $relations->belongsToMany('car', Car::class) ->through(CarUser::class); + + $relations->belongsToMany('user_custom_keys', Car::class) + ->through(CarUserWithCustomKeys::class); } }