Skip to content

Commit 6d80e08

Browse files
committed
feature #30212 [DI] Add support for "wither" methods - for greater immutable services (nicolas-grekas)
This PR was merged into the 4.3-dev branch. Discussion ---------- [DI] Add support for "wither" methods - for greater immutable services | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | symfony/symfony-docs#10991 Let's say we want to define an immutable service while still using traits for composing its optional features. A nice way to do so without hitting [the downsides of setters](https://symfony.com/doc/current/service_container/injection_types.html#setter-injection) is to use withers. Here would be an example: ```php class MyService { use LoggerAwareTrait; } trait LoggerAwareTrait { private $logger; /** * @required * @return static */ public function withLogger(LoggerInterface $logger) { $new = clone $this; $new->logger = $logger; return $new; } } $service = new MyService(); $service = $service->withLogger($logger); ``` As you can see, this nicely solves the setter issues. BUT how do you make the service container create such a service? Right now, you need to resort to complex gymnastic using the "factory" setting - manageable for only one wither, but definitely not when more are involved and not compatible with autowiring. So here we are: this PR allows configuring such services seamlessly. Using explicit configuration, it adds a 3rd parameter to method calls configuration: after the method name and its parameters, you can pass `true` and done, you just declared a wither: ```yaml services: MyService: calls: - [withLogger, ['@logger'], true] ``` In XML, you could use the new `returns-clone` attribute on the `<call>` tag. And when using autowiring, the code looks for the `@return static` annotation and turns the flag on if found. There is only one limitation: unlike services with regular setters, services with withers cannot be part of circular loops that involve calls to wither methods (unless they're declared lazy of course). Commits ------- f455d1bd97 [DI] Add support for "wither" methods - for greater immutable services
2 parents b22909a + e46b600 commit 6d80e08

File tree

1 file changed

+3
-0
lines changed

1 file changed

+3
-0
lines changed

Console/Descriptor/XmlDescriptor.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,9 @@ private function getContainerDefinitionDocument(Definition $definition, string $
357357
foreach ($calls as $callData) {
358358
$callsXML->appendChild($callXML = $dom->createElement('call'));
359359
$callXML->setAttribute('method', $callData[0]);
360+
if ($callData[2] ?? false) {
361+
$callXML->setAttribute('returns-clone', 'true');
362+
}
360363
}
361364
}
362365

0 commit comments

Comments
 (0)