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); } }