Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0e63f47

Browse files
committed
feature #19584 [DependencyInjection] Improve ParameterNotFoundException when accessing a nested parameter (wouterj)
This PR was squashed before being merged into the 3.2-dev branch (closes #19584). Discussion ---------- [DependencyInjection] Improve ParameterNotFoundException when accessing a nested parameter | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | n/a A common problem under beginners is to think that the dot notation is used to access nested arrays saved in parameters (*common here means someone asks help for this problem at least once a week on IRC*). Adding a little extra detail to the exception message and a working alternative should help pointing these people in the right direction before spending time debugging this. It's quite late in the night over here, so the wording of the exception message probably isn't great. I'm happy to accept better suggestions 😃 Commits ------- df70f06 [DependencyInjection] Improve ParameterNotFoundException when accessing a nested parameter
2 parents 68737eb + df70f06 commit 0e63f47

File tree

3 files changed

+45
-29
lines changed

3 files changed

+45
-29
lines changed

src/Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@ class ParameterNotFoundException extends InvalidArgumentException
2222
private $sourceId;
2323
private $sourceKey;
2424
private $alternatives;
25+
private $nonNestedAlternative;
2526

2627
/**
27-
* @param string $key The requested parameter key
28-
* @param string $sourceId The service id that references the non-existent parameter
29-
* @param string $sourceKey The parameter key that references the non-existent parameter
30-
* @param \Exception $previous The previous exception
31-
* @param string[] $alternatives Some parameter name alternatives
28+
* @param string $key The requested parameter key
29+
* @param string $sourceId The service id that references the non-existent parameter
30+
* @param string $sourceKey The parameter key that references the non-existent parameter
31+
* @param \Exception $previous The previous exception
32+
* @param string[] $alternatives Some parameter name alternatives
33+
* @param string|null $nonNestedAlternative The alternative parameter name when the user expected dot notation for nested parameters
3234
*/
33-
public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array())
35+
public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array(), $nonNestedAlternative = null)
3436
{
3537
$this->key = $key;
3638
$this->sourceId = $sourceId;
3739
$this->sourceKey = $sourceKey;
3840
$this->alternatives = $alternatives;
41+
$this->nonNestedAlternative = $nonNestedAlternative;
3942

4043
parent::__construct('', 0, $previous);
4144

@@ -59,6 +62,8 @@ public function updateRepr()
5962
$this->message .= ' Did you mean one of these: "';
6063
}
6164
$this->message .= implode('", "', $this->alternatives).'"?';
65+
} elseif (null !== $this->nonNestedAlternative) {
66+
$this->message .= ' You cannot access nested array items, do you want to inject "'.$this->nonNestedAlternative.'" instead?';
6267
}
6368
}
6469

src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,23 @@ public function get($name)
8181
}
8282
}
8383

84-
throw new ParameterNotFoundException($name, null, null, null, $alternatives);
84+
$nonNestedAlternative = null;
85+
if (!count($alternatives) && false !== strpos($name, '.')) {
86+
$namePartsLength = array_map('strlen', explode('.', $name));
87+
$key = substr($name, 0, -1 * (1 + array_pop($namePartsLength)));
88+
while (count($namePartsLength)) {
89+
if ($this->has($key)) {
90+
if (is_array($this->get($key))) {
91+
$nonNestedAlternative = $key;
92+
}
93+
break;
94+
}
95+
96+
$key = substr($key, 0, -1 * (1 + array_pop($namePartsLength)));
97+
}
98+
}
99+
100+
throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative);
85101
}
86102

87103
return $this->parameters[$name];

src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -71,37 +71,32 @@ public function testGetSet()
7171
}
7272
}
7373

74-
public function testGetThrowParameterNotFoundException()
74+
/**
75+
* @dataProvider provideGetThrowParameterNotFoundExceptionData
76+
*/
77+
public function testGetThrowParameterNotFoundException($parameterKey, $exceptionMessage)
7578
{
7679
$bag = new ParameterBag(array(
7780
'foo' => 'foo',
7881
'bar' => 'bar',
7982
'baz' => 'baz',
83+
'fiz' => array('bar' => array('boo' => 12)),
8084
));
8185

82-
try {
83-
$bag->get('foo1');
84-
$this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
85-
} catch (\Exception $e) {
86-
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
87-
$this->assertEquals('You have requested a non-existent parameter "foo1". Did you mean this: "foo"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
88-
}
86+
$this->setExpectedException('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $exceptionMessage);
8987

90-
try {
91-
$bag->get('bag');
92-
$this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
93-
} catch (\Exception $e) {
94-
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
95-
$this->assertEquals('You have requested a non-existent parameter "bag". Did you mean one of these: "bar", "baz"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
96-
}
88+
$bag->get($parameterKey);
89+
}
9790

98-
try {
99-
$bag->get('');
100-
$this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
101-
} catch (\Exception $e) {
102-
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
103-
$this->assertEquals('You have requested a non-existent parameter "".', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
104-
}
91+
public function provideGetThrowParameterNotFoundExceptionData()
92+
{
93+
return array(
94+
array('foo1', 'You have requested a non-existent parameter "foo1". Did you mean this: "foo"?'),
95+
array('bag', 'You have requested a non-existent parameter "bag". Did you mean one of these: "bar", "baz"?'),
96+
array('', 'You have requested a non-existent parameter "".'),
97+
98+
array('fiz.bar.boo', 'You have requested a non-existent parameter "fiz.bar.boo". You cannot access nested array items, do you want to inject "fiz" instead?'),
99+
);
105100
}
106101

107102
public function testHas()

0 commit comments

Comments
 (0)