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

Appearance settings

Commit bd4ece5

Browse filesBrowse files
[DI] Add "#[Autoconfigure]" to tell how a discovered type should be autoconfigured
1 parent a608793 commit bd4ece5
Copy full SHA for bd4ece5

File tree

3 files changed

+62
-4
lines changed
Filter options

3 files changed

+62
-4
lines changed

‎src/Symfony/Component/DependencyInjection/Loader/FileLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
+21-2Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\DependencyInjection\ContainerBuilder;
2222
use Symfony\Component\DependencyInjection\Definition;
2323
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
24+
use Symfony\Contracts\Service\Attribute\Autoconfigure;
2425

2526
/**
2627
* FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -96,7 +97,7 @@ public function registerClasses(Definition $prototype, string $namespace, string
9697
throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: "%s".', $namespace));
9798
}
9899

99-
$classes = $this->findClasses($namespace, $resource, (array) $exclude);
100+
$classes = $this->findClasses($namespace, $resource, (array) $exclude, $prototype->isAutoconfigured());
100101
// prepare for deep cloning
101102
$serializedPrototype = serialize($prototype);
102103

@@ -149,7 +150,7 @@ protected function setDefinition(string $id, Definition $definition)
149150
}
150151
}
151152

152-
private function findClasses(string $namespace, string $pattern, array $excludePatterns): array
153+
private function findClasses(string $namespace, string $pattern, array $excludePatterns, bool $autoconfigure): array
153154
{
154155
$parameterBag = $this->container->getParameterBag();
155156

@@ -167,6 +168,13 @@ private function findClasses(string $namespace, string $pattern, array $excludeP
167168
}
168169
}
169170

171+
if (80000 <= \PHP_VERSION_ID && $autoconfigure) {
172+
$parseDefinition = new \ReflectionMethod(YamlFileLoader::class, 'parseDefinition');
173+
$parseDefinition->setAccessible(true);
174+
$yamlLoader = $parseDefinition->getDeclaringClass()->newInstanceWithoutConstructor();
175+
$yamlLoader->isLoadingInstanceof = true;
176+
}
177+
170178
$pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern));
171179
$classes = [];
172180
$extRegexp = '/\\.php$/';
@@ -207,6 +215,17 @@ private function findClasses(string $namespace, string $pattern, array $excludeP
207215
if ($r->isInstantiable() || $r->isInterface()) {
208216
$classes[$class] = null;
209217
}
218+
219+
if (80000 > \PHP_VERSION_ID || !$autoconfigure) {
220+
continue;
221+
}
222+
223+
foreach ($r->getAttributes(Autoconfigure::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
224+
if (!class_exists(Autoconfigure::class)) {
225+
throw new \LogicException(sprintf('You cannot use the "%s" attribute unless Symfony Contracts 2.4+ are installed. Try running "composer require symfony/service-contracts:^2.4".', Autoconfigure::class));
226+
}
227+
$parseDefinition->invoke($yamlLoader, $class, [$this->container->registerForAutoconfiguration($class)] + (array) $attribute->getInstance(), $r->getFileName(), [], true);
228+
}
210229
}
211230

212231
// track only for new & removed files

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
+7-2Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,8 @@ private function parseDefinition(string $id, $service, string $file, array $defa
389389
];
390390
}
391391

392+
$definition = isset($service[0]) && $service[0] instanceof Definition ? array_shift($service) : null;
393+
392394
$this->checkDefinition($id, $service, $file);
393395

394396
if (isset($service['alias'])) {
@@ -423,7 +425,9 @@ private function parseDefinition(string $id, $service, string $file, array $defa
423425
return $return ? $alias : $this->container->setAlias($id, $alias);
424426
}
425427

426-
if ($this->isLoadingInstanceof) {
428+
if (null !== $definition) {
429+
// no-op
430+
} elseif ($this->isLoadingInstanceof) {
427431
$definition = new ChildDefinition('');
428432
} elseif (isset($service['parent'])) {
429433
if ('' !== $service['parent'] && '@' === $service['parent'][0]) {
@@ -627,7 +631,8 @@ private function parseDefinition(string $id, $service, string $file, array $defa
627631

628632
if (isset($defaults['bind']) || isset($service['bind'])) {
629633
// deep clone, to avoid multiple process of the same instance in the passes
630-
$bindings = isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : [];
634+
$bindings = $definition->getBindings();
635+
$bindings += isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : [];
631636

632637
if (isset($service['bind'])) {
633638
if (!\is_array($service['bind'])) {
+34Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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\Contracts\Service\Attribute;
13+
14+
/**
15+
* A tag to tell how a base type should be autoconfigured.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
20+
class Autoconfigure
21+
{
22+
public function __construct(
23+
public ?array $tags = null,
24+
public ?array $calls = null,
25+
public ?array $bind = null,
26+
public bool|string|null $lazy = null,
27+
public ?bool $public = null,
28+
public ?bool $shared = null,
29+
public ?bool $autowire = null,
30+
public ?array $properties = null,
31+
public array|string|null $configurator = null,
32+
) {
33+
}
34+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.