Skip to content

Commit 55472a5

Browse files
feature #27165 [DI] Allow binding by type+name (nicolas-grekas)
This PR was merged into the 4.2-dev branch. Discussion ---------- [DI] Allow binding by type+name | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - This would allow to bind by type + argument name, e.g.: ```yaml bind: Psr\Log\LoggerInterface $logger: @logger ``` Allows more precise targets for bindings as it will match only if both the type and the name match. Works with scalar/array types also for consistency. Commits ------- 32fc58df8b [DI] Allow binding by type+name
2 parents 7da9e78 + f6a7ab5 commit 55472a5

File tree

6 files changed

+44
-6
lines changed

6 files changed

+44
-6
lines changed

Compiler/AutowirePass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
208208
continue;
209209
}
210210
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false);
211-
$type = $type ? sprintf('is type-hinted "%s"', $type) : 'has no type-hint';
211+
$type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint';
212212

213213
throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type));
214214
}

Compiler/ResolveBindingsPass.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ protected function processValue($value, $isRoot = false)
8383
$this->unusedBindings[$bindingId] = array($key, $this->currentId);
8484
}
8585

86-
if (isset($key[0]) && '$' === $key[0]) {
86+
if (preg_match('/^(?:(?:array|bool|float|int|string) )?\$/', $key)) {
8787
continue;
8888
}
8989

@@ -123,15 +123,21 @@ protected function processValue($value, $isRoot = false)
123123
continue;
124124
}
125125

126+
$typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter);
127+
128+
if (array_key_exists($k = ltrim($typeHint, '\\').' $'.$parameter->name, $bindings)) {
129+
$arguments[$key] = $this->getBindingValue($bindings[$k]);
130+
131+
continue;
132+
}
133+
126134
if (array_key_exists('$'.$parameter->name, $bindings)) {
127135
$arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]);
128136

129137
continue;
130138
}
131139

132-
$typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
133-
134-
if (!isset($bindings[$typeHint])) {
140+
if (!$typeHint || '\\' !== $typeHint[0] || !isset($bindings[$typeHint = substr($typeHint, 1)])) {
135141
continue;
136142
}
137143

Definition.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,10 @@ public function getBindings()
859859
public function setBindings(array $bindings)
860860
{
861861
foreach ($bindings as $key => $binding) {
862+
if (0 < strpos($key, '$') && $key !== $k = preg_replace('/[ \t]*\$/', ' $', $key)) {
863+
unset($bindings[$key]);
864+
$bindings[$key = $k] = $binding;
865+
}
862866
if (!$binding instanceof BoundArgument) {
863867
$bindings[$key] = new BoundArgument($binding);
864868
}

Loader/Configurator/Traits/BindTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ trait BindTrait
3131
final public function bind($nameOrFqcn, $valueOrRef)
3232
{
3333
$valueOrRef = static::processValue($valueOrRef, true);
34-
if (isset($nameOrFqcn[0]) && '$' !== $nameOrFqcn[0] && !$valueOrRef instanceof Reference) {
34+
if (!preg_match('/^(?:(?:array|bool|float|int|string)[ \t]*+)?\$/', $nameOrFqcn) && !$valueOrRef instanceof Reference) {
3535
throw new InvalidArgumentException(sprintf('Invalid binding for service "%s": named arguments must start with a "$", and FQCN must map to references. Neither applies to binding "%s".', $this->id, $nameOrFqcn));
3636
}
3737
$bindings = $this->definition->getBindings();

Tests/Compiler/ResolveBindingsPassTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,28 @@ public function testScalarSetter()
111111

112112
$this->assertEquals(array(array('setDefaultLocale', array('fr'))), $definition->getMethodCalls());
113113
}
114+
115+
public function testTupleBinding()
116+
{
117+
$container = new ContainerBuilder();
118+
119+
$bindings = array(
120+
'$c' => new BoundArgument(new Reference('bar')),
121+
CaseSensitiveClass::class.'$c' => new BoundArgument(new Reference('foo')),
122+
);
123+
124+
$definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class);
125+
$definition->addMethodCall('setSensitiveClass');
126+
$definition->addMethodCall('setAnotherC');
127+
$definition->setBindings($bindings);
128+
129+
$pass = new ResolveBindingsPass();
130+
$pass->process($container);
131+
132+
$expected = array(
133+
array('setSensitiveClass', array(new Reference('foo'))),
134+
array('setAnotherC', array(new Reference('bar'))),
135+
);
136+
$this->assertEquals($expected, $definition->getMethodCalls());
137+
}
114138
}

Tests/Fixtures/NamedArgumentsDummy.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@ public function setApiKey($apiKey)
1818
public function setSensitiveClass(CaseSensitiveClass $c)
1919
{
2020
}
21+
22+
public function setAnotherC($c)
23+
{
24+
}
2125
}

0 commit comments

Comments
 (0)