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
[2.2] [FrameworkBundle] [Serializer] Loads the Serializer component as a service in the Framework Bundle #5347
Conversation
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | ||
use Symfony\Component\DependencyInjection\Reference; | ||
/** |
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.
empty line is needed here
I´ve got rid of the priorities as they seem to confusing. @stof Do I still need at least one normalizer to set up the Serializer service? |
Priorities are needed IMO as the order of normalizers is relevant (the first one supporting it is used). But they should behave in the same way than in all other parts of Symfony. |
@stof could you please show what those parts are so I can use them as a reference to implement that feature in this PR. Thanks. |
@loalf the registration of listeners for instance |
@stof I guess you mean this implementation, https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php, no? I´ve taken a look at this code and it does pretty much the same thing it did in my previous code so I wonder if when you say "they should behave in the same way than in all other parts of Symfony" you actually mean adding a couple of methods in the Serializer service (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Serializer/Serializer.php), namely, Serializer::addNormalizer($normalizer, $priority) and Serializer::addEncoder($encoder, $priority) to be used by the CompilerPass. |
@loalf no. You previous implementation was allowing only one reference for each priority (and so you had to keep an counter for the guessed priority) whereas the existing code uses an array for each priority to have several ones. And no, you don't need to handle the priority in the Serializer IMO. when configuring the serializer by hand, you control the registration order. The priority in tags is needed to control it, but it can be sorted at compile time. |
Sorry for the long delay to reply to this. There is one thing I am not still happy with. I created a private method, |
|
||
// Flatten the array | ||
$services = array(); | ||
array_walk_recursive($servs, function($a) use (&$services) { $services[] = $a; }); |
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.
if (!empty($servs)) {
$services = call_user_fun_array('array_merge', $servs);
}
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.
What´s that for?
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.
A way to do it more efficiently and without having to use the array by reference (and used in some other places)
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.
nice trick!
$container->getDefinition('serializer')->replaceArgument(1, $encoders); | ||
} | ||
|
||
private function findAndSortTaggedServices($tag_name, $container) |
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.
Please use camelCased names for variables
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.
and you should typehint the ContainerBuilder
@loalf IMO, you should keep the service definition, but add the tag only based on a config flag (enabled by default to make it easier to use for simple cases but allowing to disable this normalizer) framework:
serializer:
enabled: true
get_set_normalizer: false |
@stof Honestly, I don't like this kind of "magic". Since you only have to create a new service and tag it properly, what's the point of overengineering the code just for this normalizer? Why not treat it as any other normalizer/serializer you may want to load and make it explicit and transparent? @fabpot By the way, my apologies about the long delays in my responses. I've been a little bit busy lately. |
@loalf The point is, your current setup requires registering a normalizer to be usable. With my suggestion, the serializer would be usable directly (when you don't have circular references in your object graph) but you would still be able to remove the GetSetNormalizer if you don't want to use it (for instance for the case where you have circular references) |
@stof ok, I do get it. The thing is I am not a big fun of ad hoc solutions when there is already a standard way to load a normalizer (tagging it). As you said, the current setup is unusable unless you register at least one normalizer so, what about throwing an exception in the |
I agree with @loalf: no tagged services by default and an exception if none are. |
Conflicts: src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
* A new parameter has been added to the DIC: `router.request_context.base_url` | ||
You can customize it for your functional tests or for generating urls with | ||
the right base url when your are in the cli context. | ||
>>>>>>> master |
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.
merge conflict resolution problem.
@loalf Can you take my comments into account, squash your commits, and submit a PR for the docs? Thanks. |
Conflicts: src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
This is the link to the PR for the docs, https://github.com/symfony/symfony-docs/pull/1829/files, is that enough? |
Please, close this PR and carry on #6815 |
This PR is related to this one symfony/symfony#5347.
This PR was merged into the master branch. Discussion ---------- [2.3] [FrameworkBundle] [Serializer] Loads the Serializer component as a service in the Framework Bundle This PR is the same as symfony#5347 but since I am struggling to squash all the commits I better create a new one. Sorry for the inconveniences, :) Commits ------- b4e4844 Add the serializer service
This PR was merged into the 2.6-dev branch. Discussion ---------- [Serializer] Handle circular references | Q | A | ------------- | --- | Bug fix? | Yes: avoid infinite loops. Allows to improve #5347 | New feature? | yes (circular reference handler) | BC breaks? | no | Deprecations? | no | Tests pass? | yes | License | MIT | Doc PR | symfony/symfony-docs#4299 This PR adds handling of circular references in the `Serializer` component. The number of allowed iterations is configurable (one by default). The behavior when a circular reference is detected is configurable. By default an exception is thrown. Instead of throwing an exception, it's possible to register a custom handler (e.g.: a Doctrine Handler returning the object ID). Usage: ```php use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; use Symfony\Component\Serializer\Serializer; class MyObj { private $id = 1312; public function getId() { return $this->getId(); } public function getMe() { return $this; } } $normalizer = new GetSetMethodNormalizer(); $normalizer->setCircularReferenceLimit(3); $normalizer->setCircularReferenceHandler(function ($obj) { return $obj->getId(); }); $serializer = new Serializer([$normalizer]); $serializer->normalize(new MyObj()); ``` Commits ------- 48491c4 [Serializer] Handle circular references
This PR was merged into the 2.6-dev branch. Discussion ---------- [Serializer] Handle circular references | Q | A | ------------- | --- | Bug fix? | Yes: avoid infinite loops. Allows to improve symfony#5347 | New feature? | yes (circular reference handler) | BC breaks? | no | Deprecations? | no | Tests pass? | yes | License | MIT | Doc PR | symfony/symfony-docs#4299 This PR adds handling of circular references in the `Serializer` component. The number of allowed iterations is configurable (one by default). The behavior when a circular reference is detected is configurable. By default an exception is thrown. Instead of throwing an exception, it's possible to register a custom handler (e.g.: a Doctrine Handler returning the object ID). Usage: ```php use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; use Symfony\Component\Serializer\Serializer; class MyObj { private $id = 1312; public function getId() { return $this->getId(); } public function getMe() { return $this; } } $normalizer = new GetSetMethodNormalizer(); $normalizer->setCircularReferenceLimit(3); $normalizer->setCircularReferenceHandler(function ($obj) { return $obj->getId(); }); $serializer = new Serializer([$normalizer]); $serializer->normalize(new MyObj()); ``` Commits ------- 48491c4 [Serializer] Handle circular references
It looks like the Serializer service is not in the Service Container. This PR allows users to get this service through the DIC by just simple doing $container->get('serializer');
Also, by default, the Framework Bundle will load a couple of encoders (JSON and XML) and one normalizer (GetSetMethodNormalizar). If the user wants to add more encoders or normalizer he will just have to tag it, using the specials tags "serializer.encoder" and "serializer.normalizer".
Bug fix: no
Feature addition: yes
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: [comma separated list of tickets fixed by the PR]
Todo: If this PR is approved then this file
https://github.com/symfony/symfony-standard/blob/master/app/config/config.yml
should be modified for something like this
https://gist.github.com/3471185
License of the code: MIT