Skip to content

Commit 7b80c02

Browse files
[DI] Add "by-id" autowiring: a side-effect free variant of it based on the class<>id convention
1 parent 4c0006a commit 7b80c02

File tree

16 files changed

+99
-23
lines changed

16 files changed

+99
-23
lines changed

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

+1-1
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

+1-1
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

+1-1
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

+1-1
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

+28-2
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ private function getAutowiredReference($type, $autoRegister = true)
342342
return new Reference($type);
343343
}
344344

345+
if (Definition::AUTOWIRE_BY_ID === $this->currentDefinition->getAutowired()) {
346+
return;
347+
}
348+
345349
if (null === $this->types) {
346350
$this->populateAvailableTypes();
347351
}
@@ -493,10 +497,32 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint)
493497

494498
private function createTypeNotFoundMessage($type, $label)
495499
{
496-
if (!$classOrInterface = class_exists($type, false) ? 'class' : (interface_exists($type, false) ? 'interface' : null)) {
500+
$autowireById = Definition::AUTOWIRE_BY_ID === $this->currentDefinition->getAutowired();
501+
if (!$classOrInterface = class_exists($type, $autowireById) ? 'class' : (interface_exists($type, false) ? 'interface' : null)) {
497502
return sprintf('Cannot autowire %s for service "%s": Class or interface "%s" does not exist.', $label, $this->currentId, $type);
498503
}
499-
$message = sprintf('No services were found matching the "%s" %s and it cannot be auto-registered', $type, $classOrInterface);
504+
if (null === $this->types) {
505+
$this->populateAvailableTypes();
506+
}
507+
if (!$autowireById) {
508+
$message = sprintf('No services were found matching the "%s" %s and it cannot be auto-registered', $type, $classOrInterface);
509+
} elseif (isset($this->ambiguousServiceTypes[$type])) {
510+
$message = sprintf('Service "%s" does not exist. This type could be aliased to any of these existing services: "%s"', $type, implode('", "', $this->ambiguousServiceTypes[$type]));
511+
} elseif (isset($this->types[$type])) {
512+
$message = sprintf('Service "%s" does not exist. This type could be aliased to the existing "%s" service', $type, $this->types[$type]);
513+
514+
$aliases = array();
515+
foreach (array_keys($this->types, $this->types[$type]) as $type) {
516+
if ($this->container->has($type)) {
517+
$aliases[] = $type;
518+
}
519+
}
520+
if ($aliases) {
521+
$message .= sprintf('. This service is already aliased to "%s"', implode('", "', $aliases));
522+
}
523+
} else {
524+
$message = sprintf('Service "%s" does not exist', $type);
525+
}
500526

501527
return sprintf('Cannot autowire %s for service "%s": %s.', $label, $this->currentId, $message);
502528
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ private function doResolveDefinition(ChildDefinition $definition)
101101
$def->setFile($parentDef->getFile());
102102
$def->setPublic($parentDef->isPublic());
103103
$def->setLazy($parentDef->isLazy());
104-
$def->setAutowired($parentDef->isAutowired());
104+
$def->setAutowired($parentDef->getAutowired());
105105

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

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

src/Symfony/Component/DependencyInjection/Definition.php

+21-3
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;
@@ -38,7 +41,7 @@ class Definition
3841
private $abstract = false;
3942
private $lazy = false;
4043
private $decoratedService;
41-
private $autowired = false;
44+
private $autowired = 0;
4245
private $autowiringTypes = array();
4346

4447
protected $arguments;
@@ -736,20 +739,35 @@ public function setAutowiringTypes(array $types)
736739
* @return bool
737740
*/
738741
public function isAutowired()
742+
{
743+
return (bool) $this->autowired;
744+
}
745+
746+
/**
747+
* Gets the autowiring mode.
748+
*
749+
* @return int
750+
*/
751+
public function getAutowired()
739752
{
740753
return $this->autowired;
741754
}
742755

743756
/**
744757
* Sets autowired.
745758
*
746-
* @param bool $autowired
759+
* @param bool|int $autowired
747760
*
748761
* @return $this
749762
*/
750763
public function setAutowired($autowired)
751764
{
752-
$this->autowired = (bool) $autowired;
765+
$autowired = (int) $autowired;
766+
767+
if ($autowired && self::AUTOWIRE_BY_TYPE !== $autowired && self::AUTOWIRE_BY_ID !== $autowired) {
768+
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));
769+
}
770+
$this->autowired = $autowired;
753771

754772
return $this;
755773
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -734,10 +734,11 @@ private function addService($id, Definition $definition)
734734
}
735735

736736
if ($definition->isAutowired()) {
737+
$autowired = Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'types' : 'ids';
737738
$doc .= <<<EOF
738739
739740
*
740-
* This service is autowired.
741+
* This service is autowired by {$autowired}.
741742
EOF;
742743
}
743744

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ private function addService($definition, $id, \DOMElement $parent)
199199
}
200200

201201
if ($definition->isAutowired()) {
202-
$service->setAttribute('autowire', 'true');
202+
$service->setAttribute('autowire', Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id');
203203
}
204204

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

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

+1-1
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 = '';

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

+19-2
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ private function getServiceDefaults(\DOMDocument $xml, $file)
172172
}
173173
}
174174
if ($defaultsNode->hasAttribute('autowire')) {
175-
$defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire'));
175+
$defaults['autowire'] = $this->getAutowired($defaultsNode->getAttribute('autowire'), $file);
176176
}
177177
if ($defaultsNode->hasAttribute('public')) {
178178
$defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public'));
@@ -238,7 +238,7 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults =
238238
}
239239

240240
if ($value = $service->getAttribute('autowire')) {
241-
$definition->setAutowired(XmlUtils::phpize($value));
241+
$definition->setAutowired($this->getAutowired($value, $file));
242242
} elseif (isset($defaults['autowire'])) {
243243
$definition->setAutowired($defaults['autowire']);
244244
}
@@ -666,6 +666,23 @@ private function loadFromExtensions(\DOMDocument $xml)
666666
}
667667
}
668668

669+
private function getAutowired($value, $file)
670+
{
671+
if (is_bool($value = XmlUtils::phpize($value))) {
672+
return $value;
673+
}
674+
675+
if ('by-type' === $value) {
676+
return Definition::AUTOWIRE_BY_TYPE;
677+
}
678+
679+
if ('by-id' === $value) {
680+
return Definition::AUTOWIRE_BY_ID;
681+
}
682+
683+
throw new InvalidArgumentException(sprintf('Invalid autowire attribute: "by-type", "by-id", "true" or "false" expected, "%s" given in "%s".', $value, $file));
684+
}
685+
669686
/**
670687
* Converts a \DomElement object to a PHP array.
671688
*

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

+8
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,14 @@ private function parseDefinition($id, $service, $file, array $defaults)
500500

501501
$autowire = isset($service['autowire']) ? $service['autowire'] : (isset($defaults['autowire']) ? $defaults['autowire'] : null);
502502
if (null !== $autowire) {
503+
if ('by_type' === $autowire) {
504+
$autowire = Definition::AUTOWIRE_BY_TYPE;
505+
} elseif ('by_id' === $autowire) {
506+
$autowire = Definition::AUTOWIRE_BY_ID;
507+
} elseif (!is_bool($autowire)) {
508+
throw new InvalidArgumentException(sprintf('Invalid autowire attribute: "by_type", "by_id", true or false expected, "%s" given in "%s".', is_string($autowire) ? $autowire : gettype($autowire), $file));
509+
}
510+
503511
$definition->setAutowired($autowire);
504512
}
505513

src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd

+10-4
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
103103
</xsd:choice>
104104
<xsd:attribute name="public" type="boolean" />
105-
<xsd:attribute name="autowire" type="boolean" />
105+
<xsd:attribute name="autowire" type="autowire" />
106106
<xsd:attribute name="inherit-tags" type="boolean" />
107107
</xsd:complexType>
108108

@@ -131,7 +131,7 @@
131131
<xsd:attribute name="decorates" type="xsd:string" />
132132
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
133133
<xsd:attribute name="decoration-priority" type="xsd:integer" />
134-
<xsd:attribute name="autowire" type="boolean" />
134+
<xsd:attribute name="autowire" type="autowire" />
135135
<xsd:attribute name="inherit-tags" type="boolean" />
136136
</xsd:complexType>
137137

@@ -151,7 +151,7 @@
151151
<xsd:attribute name="public" type="boolean" />
152152
<xsd:attribute name="lazy" type="boolean" />
153153
<xsd:attribute name="abstract" type="boolean" />
154-
<xsd:attribute name="autowire" type="boolean" />
154+
<xsd:attribute name="autowire" type="autowire" />
155155
</xsd:complexType>
156156

157157
<xsd:complexType name="prototype">
@@ -172,7 +172,7 @@
172172
<xsd:attribute name="lazy" type="boolean" />
173173
<xsd:attribute name="abstract" type="boolean" />
174174
<xsd:attribute name="parent" type="xsd:string" />
175-
<xsd:attribute name="autowire" type="boolean" />
175+
<xsd:attribute name="autowire" type="autowire" />
176176
<xsd:attribute name="inherit-tags" type="boolean" />
177177
</xsd:complexType>
178178

@@ -279,4 +279,10 @@
279279
<xsd:pattern value="(%.+%|true|false)" />
280280
</xsd:restriction>
281281
</xsd:simpleType>
282+
283+
<xsd:simpleType name="autowire">
284+
<xsd:restriction base="xsd:string">
285+
<xsd:pattern value="(true|false|by-type|by-id)" />
286+
</xsd:restriction>
287+
</xsd:simpleType>
282288
</xsd:schema>

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function isFrozen()
6161
* This service is shared.
6262
* This method always returns the same instance of the service.
6363
*
64-
* This service is autowired.
64+
* This service is autowired by types.
6565
*
6666
* @return \Foo A Foo instance
6767
*/

src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
33
<services>
44
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" synthetic="true"/>
5-
<service id="foo" class="Foo" autowire="true"/>
5+
<service id="foo" class="Foo" autowire="by-type"/>
66
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false"/>
77
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container" public="false"/>
88
<service id="Symfony\Component\DependencyInjection\Container" alias="service_container" public="false"/>

src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ services:
55
synthetic: true
66
foo:
77
class: Foo
8-
autowire: true
8+
autowire: by_type
99
Psr\Container\ContainerInterface:
1010
alias: service_container
1111
public: false

0 commit comments

Comments
 (0)