-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DependencyInjection] Add support for named arguments #21383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I like it. |
Note that this conflicts with the implementation of #21313 that was just merged. |
Not really (AFAIU). But can't be used along with. Side-note: I've already seen some projects using arguments keys, despite it had no effect until now (simply for "increasing readability"). Shouldn't it be considered as a BC break? |
services:
App\Foo\Bar: {'@baz', 'foo', apiKey: "%mandril_api_key%"} |
@ogizanagi in my opinion no, it was explicitly documented to support only packed arrays (see my changes in |
Indeed, I'll try to adapt my PR to be able to use both syntaxes together. This would be nice but it actually doesn't work: services:
Acme\NewsletterManager: { apiKey: "%mandril_api_key%" } But this works: services:
Acme\NewsletterManager:
arguments: { apiKey: "%mandril_api_key%" } |
It would be a nice addition, I propose to do it in another PR when this one will be reviewed and merged.
Done, I rely on @weaverryan's implementation for now because conditions to rebuild the container will be the same if we add
Done! |
@kasparsklavins we are trying to find the best way to inject parameters when using autowiring and service auto-registration (#21289). It will be a brand new way to use Symfony that will change drastically the first experience for new users and allow to develop faster. |
@fabpot @ogizanagi I've tried something to support the short syntax: b8c0e7c WDYT? |
|
Re-thinking about it, it also means introducing a new keyword someday means a potential BC break for someone using the short syntax along with named arguments 😕 |
Enforce a leading |
One minor issue I see with this: when you rename a variable in php, it will now crash, but this won't be detected with applications (or bundles) with only unit-tests. |
@iltar you're right but it's already the case for traditional definitions (if you add or remove an argument it will fail) and for It's why unit testing is not enough and apps need to have a pyramid of tests including some functional and UI ones. |
@dunglas correct, however, there's a bunch of refactoring tools and find/replaces that might modify the name of a variable. Correctly removing one without causing parse errors is a lot more complex, hence this issue is faster to present itself. |
PR updated to make named arguments starting with a |
} | ||
|
||
if ($originalArguments !== $arguments) { | ||
$value->setArguments($arguments); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ksort($arguments)
before set?
private function isUsingShortSyntax(array $service) | ||
{ | ||
foreach ($service as $key => $value) { | ||
if (!is_int($key) && '$' !== substr($key, 0, 1)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be an ||
instead of &&
?
I'd write it as if (!isset($key[0]) || '$' !== $key[0]) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be an || instead of &&?
No it's correct (only int and keys starting with a $ are allowed when using short syntax)
@@ -245,7 +261,7 @@ private function parseDefinition($id, $service, $file, array $defaults) | |||
return; | |||
} | |||
|
|||
if (is_array($service) && array_values($service) === $service) { | |||
if (is_array($service) && $this->isUsingShortSyntax($service)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note that array_values checked the order of keys, whereas isUsingShortSyntax doesn't anymore, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, is it a problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no :)
private function isUsingShortSyntax(array $service) | ||
{ | ||
foreach ($service as $key => $value) { | ||
if (!is_int($key) && (isset($key[0]) && '$' !== $key[0])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the empty string case should also return false, isn't it? thus:
if (is_string($key) && ('' === $key || '$' !== $key[0])) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? If it's an empty, string, it's not a short definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's exactly what I'm saying :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
2e5cabb
to
0841285
Compare
I don't like the arguments:
$apiKey: "%mandrill_api_key%" |
I think the |
dd345af
to
8305385
Compare
86effb8
to
8a126c8
Compare
@weaverryan Can we close #21376? |
@dunglas Looks like another one where a doc PR is needed :) |
Thank you @dunglas. |
…(dunglas, nicolas-grekas) This PR was merged into the 3.3-dev branch. Discussion ---------- [DependencyInjection] Add support for named arguments | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | todo This PR introduces named arguments for services definitions. It's especially useful to inject parameters in an autowired service. It is (at least partially) an alternative to #21376 and #20738. Usage: ```yml services: _defaults: { autowire: true } Acme\NewsletterManager: { $apiKey: "%mandrill_api_key%" } # Alternative (traditional) syntax services: newsletter_manager: class: Acme\NewsletterManager arguments: $apiKey: "%mandrill_api_key%" autowire: true ``` ```php use Doctrine\ORM\EntityManager; use Psr\Log\LoggerInterface; namespace Acme; class NewsletterManager { private $logger; private $em; private $apiKey; public function __construct(LoggerInterface $logger, EntityManager $em, $apiKey) { $this->logger = $logger; $this->em = $em; $this->apiKey = $apiKey; } } ``` Commits ------- 8a126c8 [DI] Deprecate string keys in arguments 2ce36a6 [DependencyInjection] Add a new pass to check arguments validity 6e50129 [DependencyInjection] Add support for named arguments
I've at least got a docs issue opened for this! symfony/symfony-docs#7482 ... and I closed my other PR - #21376 |
The |
This breaks on Symfony 3.3.0-Beta1 because of [changes in DI](symfony/symfony#21383 (comment)). Named keys have never been officially supported.
* | ||
* @throws InvalidArgumentException | ||
* | ||
* @return array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be hinted as \ReflectionParameter[]
so the following calls make more sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method has been removed during a subsequent refactoring.
@@ -213,12 +213,14 @@ public function getArgument($index) | |||
*/ | |||
public function replaceArgument($index, $value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the phpdoc of $index needs to be updated to allow string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also ChildDefinition::getArgument doesn't work with string yet. whereas you changed the parent Definition::getArgument.
…ition (dunglas) This PR was squashed before being merged into the 3.3 branch (closes #22981). Discussion ---------- [DependencyInjection] Fix named args support in ChildDefinition | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | yes | New feature? | no <!-- don't forget updating src/**/CHANGELOG.md files --> | BC breaks? | no | Deprecations? | no <!-- don't forget updating UPGRADE-*.md files --> | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Following @Tobion's review of #21383. Commits ------- 1ab3e41 [DependencyInjection] Fix named args support in ChildDefinition
For reasons unknown to me, my currently client had tons of service definitions that looked like: service.id:
class: Foo
arguments:
foo: something
bar: somethingelse <?php
class Foo {
public function __construct($foo, $bar) {
// $foo would be something
// $bar would be somethingelse
}
} All of those broke with the introduction of these changes in 3.3.
Was this intentional? Was their use-case undocumented and thus not supported? Cause it did work exactly as expected before 3.3... |
Afaik, the keys were unused and therefore treated by sequence. Writing it down like this wasn't a supported feature either. |
That's what I figured. They were using the keys themselves though in some cases, by retrieving the arguments of the service definition, in some CompilerPass related stuff. Took me a bit to sort everything out 😅 |
This PR introduces named arguments for services definitions. It's especially useful to inject parameters in an autowired service. It is (at least partially) an alternative to #21376 and #20738.
Usage: