Skip to content

Commit

Permalink
Hydrator: Correctly hydrate custom aliases targeting targets with und…
Browse files Browse the repository at this point in the history
…erscores in their name

fixes #125
  • Loading branch information
nilmerg committed Jan 11, 2024
1 parent ae9560f commit a68f501
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 7 deletions.
21 changes: 14 additions & 7 deletions src/Hydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
41 changes: 41 additions & 0 deletions tests/HydratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'
);
}
}
3 changes: 3 additions & 0 deletions tests/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit a68f501

Please sign in to comment.