8000 feature #22060 [DI] Add "by-id" autowiring: a side-effect free varian… · sustmi/symfony@6cc9dc7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6cc9dc7

Browse files
committed
feature symfony#22060 [DI] Add "by-id" autowiring: a side-effect free variant of it based on the class<>id convention (nicolas-grekas)
This PR was merged into the 3.3-dev branch. Discussion ---------- [DI] Add "by-id" autowiring: a side-effect free variant of it based on the class<>id convention | 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 PR adds a new autowiring mode, based only on the class <> id convention. This way of autowiring is free from any conflicting behavior, which is what I was looking for to begin with. The expected DX is a bit more involving than the current way we do autowiring. But it's worth it to me, because it's plain predictable - a lot less "magic" imho. So in this mode, for each `App\Foo` type hint, a reference to an "App\Foo" service will be created. If no such service exists, an exception will be thrown. To me, this opens a nice DX: when type hinting interfaces (which is the best practice), this will tell you when you need to create the explicit interface <> id mapping that is missing - thus encourage things to be made explicit, but only when required, and gradually, in a way that will favor discoverability by devs. Of course, this is opt-in, and BC. You'd need to do eg in yaml: `autowire: by_id`. For consistency, the current mode (`autowire: true`) can be configured using `autowire: by_type`. Commits ------- c298f2a [DI] Add "by-id" autowiring: a side-effect free variant of it based on the class<>id convention
2 parents 9896f86 + c298f2a commit 6cc9dc7

File tree

18 files changed

+135
-25
lines changed

18 files changed

+135
-25
lines changed

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ private function getContainerDefinitionData(Definition $definition, $omitTags =
221221
'lazy' => $definition->isLazy(),
222222
'shared' => $definition->isShared(),
223223
'abstract' => $definition->isAbstract(),
224-
'autowire' => $definition->isAutowired(),
224+
'autowire' => $definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : false,
225225
);
226226

227227
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ protected function describeContainerDefinition(Definition $definition, array $op
182182
."\n".'- Lazy: '.($definition->isLazy() ? 'yes' : 'no')
183183
."\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no')
184184
."\n".'- Abstract: '.($definition->isAbstract() ? 'yes' : 'no')
185-
."\n".'- Autowired: '.($definition->isAutowired() ? 'yes' : 'no')
185+
."\n".'- Autowired: '.($definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : 'no')
186186
;
187187

188188
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ protected function describeContainerDefinition(Definition $definition, array $op
295295
$tableRows[] = array('Lazy', $definition->isLazy() ? 'yes' : 'no');
296296
$tableRows[] = array('Shared', $definition->isShared() ? 'yes' : 'no');
297297
$tableRows[] = array('Abstract', $definition->isAbstract() ? 'yes' : 'no');
298-
$tableRows[] = array('Autowired', $definition->isAutowired() ? 'yes' : 'no');
298+
$tableRows[] = array('Autowired', $definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : 'no');
299299

300300
if ($autowiringTypes = $definition->getAutowiringTypes(false)) {
301301
$tableRows[] = array('Autowiring Types', implode(', ', $autowiringTypes));

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ private function getContainerDefinitionDocument(Definition $definition, $id = nu
371371
$serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false');
372372
$serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false');
373373
$serviceXML->setAttribute('abstract', $definition->isAbstract() ? 'true' : 'false');
374-
$serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false');
374+
$serviceXML->setAttribute('autowired', $definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : 'false');
375375
$serviceXML->setAttribute('file', $definition->getFile());
376376

377377
$calls = $definition->getMethodCalls();

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@ private function getAutowiredReference($type, $autoRegister = true)
312312
return new Reference($type);
313313
}
314314

315+
if (Definition::AUTOWIRE_BY_ID === $this->currentDefinition->getAutowired()) {
316+
return;
317+
}
318+
315319
if (null === $this->types) {
316320
$this->populateAvailableTypes();
317321
}
@@ -462,10 +466,18 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint)
462466

463467
private function createTypeNotFoundMessage($type, $label)
464468
{
465-
if (!$classOrInterface = class_exists($type, false) ? 'class' : (interface_exists($type, false) ? 'interface' : null)) {
469+
$autowireById = Definition::AUTOWIRE_BY_ID === $this->currentDefinition->getAutowired();
470+
if (!$classOrInterface = class_exists($type, $autowireById) ? 'class' : (interface_exists($type, false) ? 'interface' : null)) {
466471
return sprintf('Cannot autowire service "%s": %s has type "%s" but this class does not exist.', $this->currentId, $label, $type);
467472
}
468-
$message = sprintf('no services were found matching the "%s" %s and it cannot be auto-registered for %s.', $type, $classOrInterface, $label);
473+
if (null === $this->types) {
474+
$this->populateAvailableTypes();
475+
}
476+
if ($autowireById) {
477+
$message = sprintf('%s references %s "%s" but no such service exists.%s', $label, $classOrInterface, $type, $this->createTypeAlternatives($type));
478+
} else {
479+
$message = sprintf('no services were found matching the "%s" %s and it cannot be auto-registered for %s.', $type, $classOrInterface, $label);
480+
}
469481

470482
return sprintf('Cannot autowire service "%s": %s', $this->currentId, $message);
471483
}

src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ private function doResolveDefinition(ChildDefinition $definition)
100100
$def->setFile($parentDef->getFile());
101101
$def->setPublic($parentDef->isPublic());
102102
$def->setLazy($parentDef->isLazy());
103-
$def->setAutowired($parentDef->isAutowired());
103+
$def->setAutowired($parentDef->getAutowired());
104104

105105
self::mergeDefinition($def, $definition);
106106

@@ -146,7 +146,7 @@ public static function mergeDefinition(Definition $def, ChildDefinition $definit
146146
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
147147
}
148148
if (isset($changes['autowired'])) {
149-
$def->setAutowired($definition->isAutowired());
149+
$def->setAutowired($definition->getAutowired());
150150
}
151151
if (isset($changes['decorated_service'])) {
152152
$decoratedService = $definition->getDecoratedService();

src/Symfony/Component/DependencyInjection/Definition.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
*/
2222
class Definition
2323
{
24+
const AUTOWIRE_BY_TYPE = 1;
25+
const AUTOWIRE_BY_ID = 2;
26+
2427
private $class;
2528
private $file;
2629
private $factory;
@@ -37,7 +40,7 @@ class Definition
3740
private $abstract = false;
3841
private $lazy = false;
3942
private $decoratedService;
40-
private $autowired = false;
43+
private $autowired = 0;
4144
private $autowiringTypes = array();
4245

4346
protected $arguments;
@@ -700,20 +703,35 @@ public function setAutowiringTypes(array $types)
700703
* @return bool
701704
*/
702705
public function isAutowired()
706+
{
707+
return (bool) $this->autowired;
708+
}
709+
710+
/**
711+
* Gets the autowiring mode.
712+
*
713+
* @return int
714+
*/
715+
public function getAutowired()
703716
{
704717
return $this->autowired;
705718
}
706719

707720
/**
708721
* Sets autowired.
709722
*
710-
* @param bool $autowired
723+
* @param bool|int $autowired
711724
*
712725
* @return $this
713726
*/
714727
public function setAutowired($autowired)
715728
{
716-
$this->autowired = (bool) $autowired;
729+
$autowired = (int) $autowired;
730+
731+
if ($autowired && self::AUTOWIRE_BY_TYPE !== $autowired && self::AUTOWIRE_BY_ID !== $autowired) {
732+
throw new InvalidArgumentException(sprintf('Invalid argument: Definition::AUTOWIRE_BY_TYPE (%d) or Definition::AUTOWIRE_BY_ID (%d) expected, %d given.', self::AUTOWIRE_BY_TYPE, self::AUTOWIRE_BY_ID, $autowired));
733+
}
734+
$this->autowired = $autowired;
717735

718736
return $this;
719737
}

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,10 +646,11 @@ private function addService($id, Definition $definition)
646646
}
647647

648648
if ($definition->isAutowired()) {
649+
$autowired = Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'types' : 'ids';
649650
$doc .= <<<EOF
650651
651652
*
652-
* This service is autowired.
653+
* This service is autowired by {$autowired}.
653654
EOF;
654655
}
655656

src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ private function addService($definition, $id, \DOMElement $parent)
195195
}
196196

197197
if ($definition->isAutowired()) {
198-
$service->setAttribute('autowire', 'true');
198+
$service->setAttribute('autowire', Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id');
199199
}
200200

201201
foreach ($definition->getAutowiringTypes(false) as $autowiringTypeValue) {

src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private function addService($id, $definition)
106106
}
107107

108108
if ($definition->isAutowired()) {
109-
$code .= " autowire: true\n";
109+
$code .= sprintf(" autowire: %s\n", Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by_type' : 'by_id');
110110
}
111111

112112
$autowiringTypesCode = '';

0 commit comments

Comments
 (0)
0