Skip to content

Commit dd83b21

Browse files
committed
[DependencyInjection] add #[AsFactory] attribute for declaring factory services
1 parent c1d73b1 commit dd83b21

9 files changed

+210
-0
lines changed

src/Symfony/Component/DependencyInjection/Attribute/Autoconfigure.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class Autoconfigure
3030
* @param array<string, mixed>|null $properties The properties to define when creating the service
3131
* @param array{string, string}|string|null $configurator A PHP function, reference or an array containing a class/reference and a method to call after the service is fully initialized
3232
* @param string|null $constructor The public static method to use to instantiate the service
33+
* @param array<string|null, string|null>|string|null $factory The factory that defines how to create the service
3334
*/
3435
public function __construct(
3536
public ?array $tags = null,
@@ -42,6 +43,7 @@ public function __construct(
4243
public ?array $properties = null,
4344
public array|string|null $configurator = null,
4445
public ?string $constructor = null,
46+
public array|string|null $factory = null,
4547
) {
4648
}
4749
}

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
CHANGELOG
22
=========
33

4+
7.4
5+
---
6+
* Add `factory` argument to the `#[Autoconfigure]` attribute to define how the service should be instantiated using a factory
7+
48
7.3
59
---
610

src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class YamlFileLoader extends FileLoader
100100
'autowire' => 'autowire',
101101
'bind' => 'bind',
102102
'constructor' => 'constructor',
103+
'factory' => 'factory',
103104
];
104105

105106
private const DEFAULTS_KEYWORDS = [

src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterAutoconfigureAttributesPassTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureRepeatedOverwrite;
2727
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureRepeatedProperties;
2828
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureRepeatedTag;
29+
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureWithExpressionFactory;
30+
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureWithInstanceExternalFactory;
31+
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureWithInvokableFactory;
32+
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureWithStaticExternalFactory;
33+
use Symfony\Component\DependencyInjection\Tests\Fixtures\AutoconfigureWithStaticSelfFactory;
34+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryDummy;
2935
use Symfony\Component\DependencyInjection\Tests\Fixtures\LazyAutoconfigured;
3036
use Symfony\Component\DependencyInjection\Tests\Fixtures\LazyLoaded;
3137
use Symfony\Component\DependencyInjection\Tests\Fixtures\MultipleAutoconfigureAttributed;
@@ -208,6 +214,88 @@ public function testStaticConstructor()
208214
$this->assertEquals([StaticConstructorAutoconfigure::class => $expected], $container->getAutoconfiguredInstanceof());
209215
}
210216

217+
public function testAutoconfigureWithStaticSelfFactory()
218+
{
219+
$container = new ContainerBuilder();
220+
$container->register('foo', AutoconfigureWithStaticSelfFactory::class)
221+
->setAutoconfigured(true);
222+
223+
$argument = new BoundArgument('foo', false, BoundArgument::INSTANCEOF_BINDING, realpath(__DIR__.'/../Fixtures/AutoconfigureWithStaticSelfFactory.php'));
224+
225+
(new RegisterAutoconfigureAttributesPass())->process($container);
226+
227+
$expected = (new ChildDefinition(''))
228+
->setFactory([null, 'create'])
229+
->setBindings(['$foo' => $argument])
230+
;
231+
$this->assertEquals([AutoconfigureWithStaticSelfFactory::class => $expected], $container->getAutoconfiguredInstanceof());
232+
}
233+
234+
public function testAutoconfigureWithStaticExternalFactory()
235+
{
236+
$container = new ContainerBuilder();
237+
$container->register('foo', AutoconfigureWithStaticExternalFactory::class)
238+
->setAutoconfigured(true);
239+
240+
$argument = new BoundArgument('foo', false, BoundArgument::INSTANCEOF_BINDING, realpath(__DIR__.'/../Fixtures/AutoconfigureWithStaticExternalFactory.php'));
241+
242+
(new RegisterAutoconfigureAttributesPass())->process($container);
243+
244+
$expected = (new ChildDefinition(''))
245+
->setFactory([FactoryDummy::class, 'create'])
246+
->setBindings(['$foo' => $argument])
247+
;
248+
$this->assertEquals([AutoconfigureWithStaticExternalFactory::class => $expected], $container->getAutoconfiguredInstanceof());
249+
}
250+
251+
public function testAutoconfigureWithInstanceExternalFactory()
252+
{
253+
$container = new ContainerBuilder();
254+
$container->register('foo', AutoconfigureWithInstanceExternalFactory::class)
255+
->setAutoconfigured(true);
256+
257+
$argument = new BoundArgument('foo', false, BoundArgument::INSTANCEOF_BINDING, realpath(__DIR__.'/../Fixtures/AutoconfigureWithInstanceExternalFactory.php'));
258+
259+
(new RegisterAutoconfigureAttributesPass())->process($container);
260+
261+
$expected = (new ChildDefinition(''))
262+
->setFactory([new Reference('factory_for_autoconfigure'), 'createStatic'])
263+
->setBindings(['$foo' => $argument])
264+
;
265+
$this->assertEquals([AutoconfigureWithInstanceExternalFactory::class => $expected], $container->getAutoconfiguredInstanceof());
266+
}
267+
268+
public function testAutoconfigureWithInvokableFactory()
269+
{
270+
$container = new ContainerBuilder();
271+
$container->register('foo', AutoconfigureWithInvokableFactory::class)
272+
->setAutoconfigured(true);
273+
274+
$argument = new BoundArgument('foo', false, BoundArgument::INSTANCEOF_BINDING, realpath(__DIR__.'/../Fixtures/AutoconfigureWithInvokableFactory.php'));
275+
276+
(new RegisterAutoconfigureAttributesPass())->process($container);
277+
278+
$expected = (new ChildDefinition(''))
279+
->setFactory([new Reference('factory_for_autoconfigure'), '__invoke'])
280+
->setBindings(['$foo' => $argument])
281+
;
282+
$this->assertEquals([AutoconfigureWithInvokableFactory::class => $expected], $container->getAutoconfiguredInstanceof());
283+
}
284+
285+
public function testAutoconfigureWithExpressionFactory()
286+
{
287+
$container = new ContainerBuilder();
288+
$container->register('foo', AutoconfigureWithExpressionFactory::class)
289+
->setAutoconfigured(true);
290+
291+
(new RegisterAutoconfigureAttributesPass())->process($container);
292+
293+
$expected = (new ChildDefinition(''))
294+
->setFactory('@=service("factory_for_autoconfigure").create()')
295+
;
296+
$this->assertEquals([AutoconfigureWithExpressionFactory::class => $expected], $container->getAutoconfiguredInstanceof());
297+
}
298+
211299
public function testLazyServiceAttribute()
212300
{
213301
$container = new ContainerBuilder();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
13+
14+
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
15+
16+
#[Autoconfigure(factory: '@=service("factory_for_autoconfigure").create()')]
17+
class AutoconfigureWithExpressionFactory
18+
{
19+
public function __construct(public readonly string $foo)
20+
{
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
13+
14+
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
15+
16+
#[Autoconfigure(bind: ['$foo' => 'foo'], factory: ['@factory_for_autoconfigure', 'createStatic'])]
17+
class AutoconfigureWithInstanceExternalFactory
18+
{
19+
public function __construct(public readonly string $foo)
20+
{
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
13+
14+
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
15+
16+
#[Autoconfigure(bind: ['$foo' => 'foo'], factory: '@factory_for_autoconfigure')]
17+
class AutoconfigureWithInvokableFactory
18+
{
19+
public function __construct(public readonly string $foo)
20+
{
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
13+
14+
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
15+
16+
#[Autoconfigure(bind: ['$foo' => 'foo'], factory: [FactoryDummy::class, 'create'])]
17+
class AutoconfigureWithStaticExternalFactory
18+
{
19+
public function __construct(public readonly string $foo)
20+
{
21+
}
22+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
13+
14+
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
15+
16+
#[Autoconfigure(bind: ['$foo' => 'foo'], factory: [null, 'create'])]
17+
class AutoconfigureWithStaticSelfFactory
18+
{
19+
public function __construct(public readonly string $foo)
20+
{
21+
}
22+
23+
public static function create(string $foo): static
24+
{
25+
return new self($foo);
26+
}
27+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy