Skip to content

Commit a7fda15

Browse files
committed
[OptionsResolver] Fix missing prototype key in nested error paths
1 parent 105ca41 commit a7fda15

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/Symfony/Component/OptionsResolver/OptionsResolver.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,11 @@ public function offsetGet(mixed $option, bool $triggerDeprecation = true): mixed
964964
$resolver = new self();
965965
$resolver->prototype = false;
966966
$resolver->parentsOptions = $this->parentsOptions;
967+
968+
if ($this->prototype && null !== $this->prototypeIndex && null !== ($parentOptionKey = array_key_last($resolver->parentsOptions))) {
969+
$resolver->parentsOptions[$parentOptionKey] .= \sprintf('[%s]', $this->prototypeIndex);
970+
}
971+
967972
$resolver->parentsOptions[] = $option;
968973
foreach ($this->nested[$option] as $closure) {
969974
$closure($resolver, $this);

src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,4 +2566,46 @@ public function testPrototypeDefinition()
25662566

25672567
$this->assertSame($expectedOptions, $actualOptions);
25682568
}
2569+
2570+
public function testNestedPrototypeErrorPathHasFullContext()
2571+
{
2572+
$resolver = new OptionsResolver();
2573+
2574+
$resolver->setDefault('connections', static function (OptionsResolver $connResolver) {
2575+
$connResolver->setPrototype(true);
2576+
$connResolver->setRequired(['host', 'database']);
2577+
$connResolver->setDefault('user', 'root');
2578+
2579+
$connResolver->setDefault('replicas', static function (OptionsResolver $replicaResolver) {
2580+
$replicaResolver->setPrototype(true);
2581+
$replicaResolver->setRequired(['host']);
2582+
$replicaResolver->setDefault('user', 'read_only');
2583+
});
2584+
});
2585+
2586+
$this->expectException(MissingOptionsException::class);
2587+
$this->expectExceptionMessage('The required option "connections[main_db][replicas][1][host]" is missing.');
2588+
2589+
$options = [
2590+
'connections' => [
2591+
'main_db' => [
2592+
'host' => 'localhost',
2593+
'database' => 'app_db',
2594+
'replicas' => [
2595+
['host' => 'replica-01.local', 'user' => 'read_only'],
2596+
['user' => 'other_user'], // Index 1 -> "host" is missing here
2597+
],
2598+
],
2599+
'audit_db' => [
2600+
'host' => 'audit.local',
2601+
'database' => 'audit_db',
2602+
'replicas' => [
2603+
['host' => 'audit-replica.local'],
2604+
],
2605+
],
2606+
],
2607+
];
2608+
2609+
$resolver->resolve($options);
2610+
}
25692611
}

0 commit comments

Comments
 (0)