You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feature #17608 [DependencyInjection] Autowiring: add setter injection support (dunglas)
This PR was merged into the 3.2-dev branch.
Discussion
----------
[DependencyInjection] Autowiring: add setter injection support
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | n/a
| License | MIT
| Doc PR | todo
Add support for setter injection in the Dependency Injection Component.
Setter injection should be avoided when possible. However, there is some legitimate use cases for it. This PR follows a proposal of @weaverryan to ease using [DunglasActionBundle](https://github.com/dunglas/DunglasActionBundle) with #16863. The basic idea is to include a setter for the required service in the trait and let the DependencyInjection Component autowire the dependency using the setter.
This way, a newcomer can use the trait without having to create or modify the constructor of the action.
/cc @derrabus
Commits
-------
a0d7cbe [DependencyInjection] Autowiring: add setter injection support
Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,7 @@ CHANGELOG
4
4
3.2.0
5
5
-----
6
6
7
+
* added support for setter autowiring
7
8
* allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()`
8
9
* added support for PHP constants in YAML configuration files
9
10
* deprecated the ability to set or unset a private service with the `Container::set()` method
if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
120
153
continue;
121
154
}
@@ -124,7 +157,11 @@ private function completeDefinition($id, Definition $definition)
124
157
if (!$typeHint = $parameter->getClass()) {
125
158
// no default value? Then fail
126
159
if (!$parameter->isOptional()) {
127
-
thrownewRuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id));
160
+
if ($isConstructor) {
161
+
thrownewRuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id));
162
+
}
163
+
164
+
return;
128
165
}
129
166
130
167
// specifically pass the default value
@@ -139,24 +176,35 @@ private function completeDefinition($id, Definition $definition)
// The exception code is set to 1 if the exception must be thrown even if it's a setter
191
+
if (1 === $e->getCode() || $isConstructor) {
192
+
throw$e;
193
+
}
194
+
195
+
return;
152
196
}
153
197
}
154
198
}
155
199
} catch (\ReflectionException$e) {
156
200
// Typehint against a non-existing class
157
201
158
202
if (!$parameter->isDefaultValueAvailable()) {
159
-
thrownewRuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $e->getMessage()), 0, $e);
203
+
if ($isConstructor) {
204
+
thrownewRuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $e->getMessage()), 0, $e);
205
+
}
206
+
207
+
return;
160
208
}
161
209
162
210
$value = $parameter->getDefaultValue();
@@ -168,7 +216,12 @@ private function completeDefinition($id, Definition $definition)
168
216
// it's possible index 1 was set, then index 0, then 2, etc
169
217
// make sure that we re-order so they're injected as expected
thrownewRuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices));
322
+
thrownewRuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices), 1);
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "setter_injection_collision". Multiple services exist for this interface (c1, c2).
0 commit comments