Skip to content
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

Closed
wants to merge 26 commits into from

Conversation

loalf
Copy link
Contributor

@loalf loalf commented Aug 25, 2012

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

@travisbot
Copy link

This pull request fails (merged 881e9a6 into d1be451).

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
/**
Copy link
Contributor

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

@loalf
Copy link
Contributor Author

loalf commented Aug 26, 2012

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?

@travisbot
Copy link

This pull request fails (merged 0278df8 into d1be451).

@stof
Copy link
Member

stof commented Aug 26, 2012

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.

@loalf
Copy link
Contributor Author

loalf commented Aug 26, 2012

@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.

@stof
Copy link
Member

stof commented Aug 26, 2012

@loalf the registration of listeners for instance

@loalf
Copy link
Contributor Author

loalf commented Aug 29, 2012

@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.

@stof
Copy link
Member

stof commented Aug 29, 2012

@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.

@loalf
Copy link
Contributor Author

loalf commented Sep 3, 2012

Sorry for the long delay to reply to this.

There is one thing I am not still happy with. I created a private method, findAndSortTaggedServices, in the SerializerCompiler class but, to be honest, I think this method should be on the Container class so everyone could benefit of this feature. Any comment?


// Flatten the array
$services = array();
array_walk_recursive($servs, function($a) use (&$services) { $services[] = $a; });
Copy link
Member

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);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What´s that for?

Copy link
Member

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)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice trick!

@travisbot
Copy link

This pull request passes (merged e579aac into d1be451).

@travisbot
Copy link

This pull request passes (merged 91812e2 into d1be451).

@travisbot
Copy link

This pull request passes (merged 4d6fdc0 into d1be451).

$container->getDefinition('serializer')->replaceArgument(1, $encoders);
}

private function findAndSortTaggedServices($tag_name, $container)
Copy link
Member

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

Copy link
Member

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

@stof
Copy link
Member

stof commented Oct 29, 2012

@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

@loalf
Copy link
Contributor Author

loalf commented Nov 4, 2012

@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.

@stof
Copy link
Member

stof commented Nov 4, 2012

@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)

@loalf
Copy link
Contributor Author

loalf commented Nov 4, 2012

@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 SerializerPass class if there aren't any normalizer/encoder registered?

@loalf
Copy link
Contributor Author

loalf commented Nov 13, 2012

@stof @fabpot any thoughts on this?

@fabpot
Copy link
Member

fabpot commented Dec 14, 2012

I agree with @loalf: no tagged services by default and an exception if none are.

* 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge conflict resolution problem.

@fabpot
Copy link
Member

fabpot commented Jan 9, 2013

@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
@loalf
Copy link
Contributor Author

loalf commented Jan 19, 2013

This is the link to the PR for the docs, https://github.com/symfony/symfony-docs/pull/1829/files, is that enough?

@loalf
Copy link
Contributor Author

loalf commented Jan 20, 2013

Please, close this PR and carry on #6815

@fabpot fabpot closed this Jan 20, 2013
77web pushed a commit to 77web/symfony-docs that referenced this pull request Nov 23, 2013
ondrejmirtes pushed a commit to ondrejmirtes/symfony that referenced this pull request Nov 25, 2013
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
fabpot added a commit that referenced this pull request Oct 20, 2014
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
sandergo90 pushed a commit to sandergo90/symfony that referenced this pull request Jul 4, 2019
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants