-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DI] Add "inherit-tags" with configurable defaults + same for "public", "tags" & "autowire" #21071
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
Looks like a good idea to me. What about aliases, though? service_defaults:
public: ['aliases'] # aliases are public whereas services are private
service_defaults:
public: true # default: aliases and services are public <=> ['aliases', 'services']
service_defaults:
public: false # aliases and services are private <=> [] (It'll need a special treatment for the |
What about adding tags like this? I often find myself with a specific service definition file that contains a specific type of services. Think of a file for form types, they all have the same tag. It would be really nice if I could use this feature to automatically tag all definitions in that file by this implicit parent definition. |
👍, you should add this new section here or the ContainerBuilder will throw an exception. |
ac66912
to
cd74550
Compare
Minor comment: could we please take some time to think about this proposal before merging it? This kind of changes can have a deep impact in how developers use Symfony. Personally I don't have an opinion about the idea yet ... but I don't like the implementation. It doesn't feel "natural" for Symfony. |
As soon as it doesn't behaves blindly as a pseudo parent definition, but rather as a context/configuration exploitable by the loaders, it looks good to me. Hence, I don't really like the |
@@ -146,9 +146,10 @@ private function parseDefinitions($content, $file) | |||
if (!is_array($content['services'])) { | |||
throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file)); | |||
} | |||
$defaults = isset($content['service_defaults']) ? $content['service_defaults'] : 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.
I think unsupported keys should throw an exception to be consistent with the rest of the loader.
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
@javiereguiluz don't worry we have a process for that, this PR is no exception. @ogizanagi I'm 👎 on |
cd74550
to
93664c8
Compare
PR completed for YamlLoader. If someone would like to work on XmlLoader, I'd happily accept a PR against my branch! |
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.
👍
@@ -176,7 +188,7 @@ private function parseDefinition($id, $service, $file) | |||
static::checkDefinition($id, $service, $file); | |||
|
|||
if (isset($service['alias'])) { | |||
$public = !array_key_exists('public', $service) || (bool) $service['public']; | |||
$public = array_key_exists('public', $service) ? (bool) $service['public'] : !empty($defaults['public']); |
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.
Any reason to define this variable twice? One doing array_key_exists
other isset
?
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.
these are not on the same path, and don't have the same semantic (don't forget about ChildDefinition on the other path.)
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.
I had services defined: (Symfony 3.1.8):
foo:
class: My\FooService
bar:
alias: foo
I could access bar
service in my controller because it was public by default. After this change here my aliased service is private by default, thus the service is not accessible in controller.
Shouldn't this be mentioned somewhere? I couldn't find any info about 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.
Good catch. That's a bug. See #21219
throw new InvalidArgumentException(sprintf('Service defaults must be an array, "%s" given in "%s".', gettype($defaults), $file)); | ||
} | ||
foreach ($defaults as $key => $default) { | ||
if (!in_array($key, $defaultKeys)) { |
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.
Perhaps go strict here?
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 this way for consistency with the many other in_array
in this file, good enough anyway
I like the idea! What about using just defaults:
public: false
autowire: ['_construct', 'set*']
services:
foo:
class: Foo The best looking config is: services:
defaults:
public: false
autowire: ['_construct', 'set*']
'Foo\Bar': {} But I'm not sure that it's ok to deprecate some services names like |
Really? The one above looks more intuitive to me... defaults: #...
services: #... that is. Looking at it like this looks good... then again; if parameters are involved ( Meaning either |
The root namespace is used for container extensions configuration, that means there is a potential for collision with an existing bundle that uses this "defaults" name. framework: #...
services: #...
defaults: #... it's not intuitive at all that |
What about adding an underscore in this way? services:
_defaults:
#... |
Perhaps |
I doubt |
Think you're right.. just typed it out to visualize in fact. It looks good (imo.) but indeed.. you need to know it.
|
What about using something that sounds more specific to yaml such as |
|
@nicolas-grekas I was thinking about a tag returning something similar to the JavaScript |
+1 for |
93664c8
to
b7ccc56
Compare
Just for inspiration from @nette, there is similar tool, that decorates specific classes/types of classes: See this article - jump to "Decorator Extension to the Rescue" headline. And this Tweet: https://twitter.com/VotrubaT/status/812802092356276224 I'm amazed, how similar these tools are :) |
What about add |
@grachevko How would that look like? From example I understand it's global setup for all services. |
@TomasVotruba not a global. This PR add |
@grachevko Ah. That's a pity. I was looking forward to get rid of Console, EventSubscriber, FormType etc. tags. I'll work on that Decorator feature then :) |
👍 |
1 similar comment
👍 |
9545899
to
88b99fb
Compare
88b99fb
to
beec1cf
Compare
Thank you @nicolas-grekas. |
…ame for "public", "tags" & "autowire" (nicolas-grekas, ogizanagi) This PR was merged into the 3.3-dev branch. Discussion ---------- [DI] Add "inherit-tags" with configurable defaults + same for "public", "tags" & "autowire" | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #20048 | License | MIT | Doc PR | - Instead of making services private by default (#20048), which is going to create a big migration burden that might not be worth it, I'd like to propose the idea of changing the default for the current file. Having a place to redefine some defaults, this can also be used to enable autowiring for a file, making it much lighter in the end. This PR handles defaults for "public", "autowired" and "tags". Not sure the other options need a configurable default. Please comment if you think otherwise. Short example (the feat is more interesting with a longer list of services): ```yaml services: _defaults: public: false autowire: ['_construct', 'set*'] foo: class: Foo ``` ```xml <?xml version="1.0" encoding="utf-8"?> <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"> <services> <defaults public="false"> <autowire>__construct</autowire> <tag name="foo"/> </defaults> </services> </container> ``` ping @dunglas @weaverryan Commits ------- beec1cf [DI] Allow definitions to inherit tags from parent context 05f24d5 [DI] Add "defaults" tag to XML services configuration 7b4a18b [DI] Add "_defaults" key to Yaml services configuration
The new |
…gizanagi) This PR was merged into the 3.3-dev branch. Discussion ---------- [DI] Fixes aliases visibility with and without defaults | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #21071 (comment) | License | MIT | Doc PR | N/A Commits ------- f1cc090 [DI] Fixes aliases visibility with and without defaults
…izanagi) This PR was merged into the 3.3-dev branch. Discussion ---------- [DI] Add Yaml syntax for short services definition | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | N/A | License | MIT | Doc PR | todo In my experience, most (at least, a lot) of the service definitions in an end-application only require the class and constructor arguments. #21133 allows to get rid of the `class` attribute by using the service id. Which means only arguments remain for most use-cases. Hence, we could support this syntax: #### Before: ```yml services: App\Foo\Bar: arguments: ['@baz', 'foo', '%qux%'] ``` #### After: ```yml services: App\Foo\Bar: ['@baz', 'foo', '%qux%'] ``` It works especially well along with services `_defaults` introduced in #21071 : ```yml services: _defaults: public: false autowire: ['set*'] tags: ['serializer.normalizer'] App\Serializer\FooNormalizer: ['@baz', 'foo', '%qux%'] ``` Commits ------- 83b599c [DI] Add Yaml syntax for short services definition
Instead of making services private by default (#20048), which is going to create a big migration burden that might not be worth it, I'd like to propose the idea of changing the default for the current file.
Having a place to redefine some defaults, this can also be used to enable autowiring for a file, making it much lighter in the end.
This PR handles defaults for "public", "autowired" and "tags". Not sure the other options need a configurable default. Please comment if you think otherwise.
Short example (the feat is more interesting with a longer list of services):
ping @dunglas @weaverryan