Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdc3f5e7

Browse files
[DependencyInjection] Add support for autowiring services as closures when using#[Autowire]
1 parentd6ddbfe commitdc3f5e7

File tree

4 files changed

+149
-3
lines changed

4 files changed

+149
-3
lines changed

‎src/Symfony/Component/DependencyInjection/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ CHANGELOG
1515
* Allow to trim XML service parameters value by using`trim="true"` attribute
1616
* Allow extending the`Autowire` attribute
1717
* Add`#[Exclude]` to skip autoregistering a class
18+
* Add support for autowiring services as closures when using`#[Autowire]`
1819

1920
6.2
2021
---

‎src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php‎

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespaceSymfony\Component\DependencyInjection\Compiler;
1313

1414
useSymfony\Component\Config\Resource\ClassExistenceResource;
15+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1516
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1617
useSymfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
1718
useSymfony\Component\DependencyInjection\Attribute\Autowire;
@@ -291,17 +292,37 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
291292
continue;
292293
}
293294

295+
$type = ProxyHelper::exportType($parameter,true);
296+
294297
if ($checkAttributes) {
295-
foreach ([TaggedIterator::class, TaggedLocator::class, Autowire::class, MapDecorated::class]as$attributeClass) {
296-
foreach ($parameter->getAttributes($attributeClass, Autowire::class ===$attributeClass ? \ReflectionAttribute::IS_INSTANCEOF :0)as$attribute) {
298+
foreach ($parameter->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF)as$attribute) {
299+
$arguments[$index] =$v =$this->processAttribute($attribute->newInstance(),$parameter->allowsNull());
300+
301+
if ('Closure' !==$type || !$vinstanceof Reference && !\is_array($v)) {
302+
continue2;
303+
}
304+
305+
if (\is_array($v)) {
306+
$arguments[$index] = (newDefinition('Closure'))
307+
->setFactory(['Closure','fromCallable'])
308+
->setArguments([$v + [1 =>'__invoke']]);
309+
}elseif ($this->container->has($v) &&'Closure' !== (($def =$this->container->findDefinition($v))->getClass() ?: (['Closure','fromCallable'] ===$def->getFactory() ?'Closure' :null))) {
310+
$arguments[$index] =newServiceClosureArgument($v);
311+
}
312+
313+
continue2;
314+
}
315+
316+
foreach ([TaggedIterator::class, TaggedLocator::class, MapDecorated::class]as$attributeClass) {
317+
foreach ($parameter->getAttributes($attributeClass)as$attribute) {
297318
$arguments[$index] =$this->processAttribute($attribute->newInstance(),$parameter->allowsNull());
298319

299320
continue3;
300321
}
301322
}
302323
}
303324

304-
if (!$type = ProxyHelper::exportType($parameter,true)) {
325+
if (!$type) {
305326
if (isset($arguments[$index])) {
306327
continue;
307328
}

‎src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
2222
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorasArgumentServiceLocator;
2323
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
24+
useSymfony\Component\DependencyInjection\Attribute\Autowire;
2425
useSymfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
2526
useSymfony\Component\DependencyInjection\Compiler\PassConfig;
2627
useSymfony\Component\DependencyInjection\Container;
@@ -1651,6 +1652,38 @@ public function testClosure()
16511652

16521653
$this->assertStringEqualsFile(self::$fixturesPath.'/php/closure.php',$dumper->dump());
16531654
}
1655+
1656+
publicfunctiontestAutowireClosure()
1657+
{
1658+
$container =newContainerBuilder();
1659+
$container->register('foo', Foo::class)
1660+
->setPublic('true');
1661+
$container->register('baz', \Closure::class)
1662+
->setFactory(['Closure','fromCallable'])
1663+
->setArguments(['var_dump'])
1664+
->setPublic('true');
1665+
$container->register('bar', LazyConsumer::class)
1666+
->setPublic('true')
1667+
->setAutowired(true);
1668+
$container->compile();
1669+
$dumper =newPhpDumper($container);
1670+
1671+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/autowire_closure.php',$dumper->dump(['class' =>'Symfony_DI_PhpDumper_Test_Autowire_Closure']));
1672+
1673+
requireself::$fixturesPath.'/php/autowire_closure.php';
1674+
1675+
$container =new \Symfony_DI_PhpDumper_Test_Autowire_Closure();
1676+
1677+
$this->assertInstanceOf(Foo::class,$container->get('foo'));
1678+
$this->assertInstanceOf(LazyConsumer::class,$bar =$container->get('bar'));
1679+
$this->assertInstanceOf(\Closure::class,$bar->foo);
1680+
$this->assertInstanceOf(\Closure::class,$bar->baz);
1681+
$this->assertInstanceOf(\Closure::class,$bar->buz);
1682+
$this->assertSame($container->get('foo'), ($bar->foo)());
1683+
$this->assertSame($container->get('baz'),$bar->baz);
1684+
$this->assertInstanceOf(Foo::class,$fooClone = ($bar->buz)());
1685+
$this->assertNotSame($container->get('foo'),$fooClone);
1686+
}
16541687
}
16551688

16561689
class Rot13EnvVarProcessorimplements EnvVarProcessorInterface
@@ -1676,3 +1709,16 @@ public function __construct(\stdClass $a, \stdClass $b)
16761709
$this->bClone =clone$b;
16771710
}
16781711
}
1712+
1713+
class LazyConsumer
1714+
{
1715+
publicfunction__construct(
1716+
#[Autowire(service:'foo')]
1717+
public\Closure$foo,
1718+
#[Autowire(service:'baz')]
1719+
public\Closure$baz,
1720+
#[Autowire([newReference('foo'),'cloneFoo'])]
1721+
public\Closure$buz,
1722+
) {
1723+
}
1724+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
useSymfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
useSymfony\Component\DependencyInjection\ContainerInterface;
5+
useSymfony\Component\DependencyInjection\Container;
6+
useSymfony\Component\DependencyInjection\Exception\LogicException;
7+
useSymfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
8+
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
9+
useSymfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
useSymfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
12+
/**
13+
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
14+
*/
15+
class Symfony_DI_PhpDumper_Test_Autowire_Closureextends Container
16+
{
17+
protected$parameters = [];
18+
protectedreadonly\WeakReference$ref;
19+
20+
publicfunction__construct()
21+
{
22+
$this->ref = \WeakReference::create($this);
23+
$this->services =$this->privates = [];
24+
$this->methodMap = [
25+
'bar' =>'getBarService',
26+
'baz' =>'getBazService',
27+
'foo' =>'getFooService',
28+
];
29+
30+
$this->aliases = [];
31+
}
32+
33+
publicfunctioncompile():void
34+
{
35+
thrownewLogicException('You cannot compile a dumped container that was already compiled.');
36+
}
37+
38+
publicfunctionisCompiled():bool
39+
{
40+
returntrue;
41+
}
42+
43+
/**
44+
* Gets the public 'bar' shared autowired service.
45+
*
46+
* @return \Symfony\Component\DependencyInjection\Tests\Dumper\LazyConsumer
47+
*/
48+
protectedstaticfunctiongetBarService($container)
49+
{
50+
$containerRef =$container->ref;
51+
52+
return$container->services['bar'] =new \Symfony\Component\DependencyInjection\Tests\Dumper\LazyConsumer(#[\Closure(name:'foo', class:'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo')]function ()use ($containerRef) {
53+
$container =$containerRef->get();
54+
55+
return ($container->services['foo'] ??=new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo());
56+
}, ($container->services['baz'] ??self::getBazService($container)), ($container->services['foo'] ??=new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo())->cloneFoo(...));
57+
}
58+
59+
/**
60+
* Gets the public 'baz' shared service.
61+
*
62+
* @return \Closure
63+
*/
64+
protectedstaticfunctiongetBazService($container)
65+
{
66+
return$container->services['baz'] =\var_dump(...);
67+
}
68+
69+
/**
70+
* Gets the public 'foo' shared service.
71+
*
72+
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\Foo
73+
*/
74+
protectedstaticfunctiongetFooService($container)
75+
{
76+
return$container->services['foo'] =new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo();
77+
}
78+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp