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

Related Doctrine Entities fail with empty document? #3

Open
drewclauson opened this issue Nov 19, 2015 · 16 comments
Open

Related Doctrine Entities fail with empty document? #3

drewclauson opened this issue Nov 19, 2015 · 16 comments
Assignees

Comments

@drewclauson
Copy link

When I try to serialize a doctrine that has related entities, I get a blank 500 error and have to dig through my logs to figure out what happened.

It looks like it's boiling down to a nesting max depth error:

[Thu Nov 19 11:58:08.370490 2015] [:error] [pid 18288] [client 10.0.0.70:50204] PHP Fatal error:  Maximum function nesting level of '256' reached, aborting! in Unknown on line 0

Any ideas on serializing related Doctrine entities?

@drewclauson
Copy link
Author

Here's an additional snippet of the log output (gets really long otherwise)

[Thu Nov 19 12:03:45.622988 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP Fatal error:  Maximum function nesting level of '256' reached, aborting! in /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php on line 176
[Thu Nov 19 12:03:45.623039 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP Stack trace:
[Thu Nov 19 12:03:45.623046 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   1. {main}() /var/www/WinStreamAPI/web/app_dev.php:0
[Thu Nov 19 12:03:45.623053 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   2. Symfony\\Component\\HttpKernel\\Kernel->handle($request = *uninitialized*, $type = *uninitialized*, $catch = *uninitialized*) /var/www/WinStreamAPI/web/app_dev.php:33
[Thu Nov 19 12:03:45.623061 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   3. Symfony\\Component\\HttpKernel\\DependencyInjection\\ContainerAwareHttpKernel->handle($request = *uninitialized*, $type = *uninitialized*, $catch = *uninitialized*) /var/www/WinStreamAPI/app/bootstrap.php.cache:2444
[Thu Nov 19 12:03:45.623067 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   4. Symfony\\Component\\HttpKernel\\HttpKernel->handle($request = *uninitialized*, $type = *uninitialized*, $catch = *uninitialized*) /var/www/WinStreamAPI/app/bootstrap.php.cache:3222
[Thu Nov 19 12:03:45.623073 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   5. Symfony\\Component\\HttpKernel\\HttpKernel->handleRaw($request = *uninitialized*, $type = *uninitialized*) /var/www/WinStreamAPI/app/bootstrap.php.cache:3071
[Thu Nov 19 12:03:45.623079 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   6. call_user_func_array:{/var/www/WinStreamAPI/app/bootstrap.php.cache:3109}(*uninitialized*, *uninitialized*) /var/www/WinStreamAPI/app/bootstrap.php.cache:3109
[Thu Nov 19 12:03:45.623084 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   7. REST\\PlayBundle\\Controller\\PlayController->indexAction() /var/www/WinStreamAPI/app/bootstrap.php.cache:3109
[Thu Nov 19 12:03:45.623090 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   8. NilPortugues\\Serializer\\Serializer->serialize($value = *uninitialized*) /var/www/WinStreamAPI/src/REST/PlayBundle/Controller/PlayController.php:39
[Thu Nov 19 12:03:45.623096 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP   9. NilPortugues\\Serializer\\Serializer->serializeData($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:117
[Thu Nov 19 12:03:45.623102 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  10. NilPortugues\\Serializer\\Serializer->serializeArray($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:156
[Thu Nov 19 12:03:45.623107 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  11. NilPortugues\\Serializer\\Serializer->serializeData($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:420
[Thu Nov 19 12:03:45.623113 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  12. NilPortugues\\Serializer\\DeepCopySerializer->serializeObject($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:150
[Thu Nov 19 12:03:45.623119 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  13. NilPortugues\\Serializer\\Serializer->serializeInternalClass($value = *uninitialized*, $className = *uninitialized*, $ref = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/DeepCopySerializer.php:34
[Thu Nov 19 12:03:45.623125 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  14. array_map(*uninitialized*, *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:458
[Thu Nov 19 12:03:45.623130 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  15. NilPortugues\\Serializer\\Serializer->serializeData($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:458
[Thu Nov 19 12:03:45.623145 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  16. NilPortugues\\Serializer\\DeepCopySerializer->serializeObject($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:150
[Thu Nov 19 12:03:45.623151 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  17. NilPortugues\\Serializer\\Serializer->serializeInternalClass($value = *uninitialized*, $className = *uninitialized*, $ref = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/DeepCopySerializer.php:34
[Thu Nov 19 12:03:45.623156 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  18. array_map(*uninitialized*, *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:458
[Thu Nov 19 12:03:45.623162 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  19. NilPortugues\\Serializer\\Serializer->serializeData($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:458
[Thu Nov 19 12:03:45.623179 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  20. NilPortugues\\Serializer\\DeepCopySerializer->serializeObject($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:150
[Thu Nov 19 12:03:45.623185 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  21. NilPortugues\\Serializer\\Serializer->serializeInternalClass($value = *uninitialized*, $className = *uninitialized*, $ref = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/DeepCopySerializer.php:34
[Thu Nov 19 12:03:45.623190 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  22. array_map(*uninitialized*, *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:458
[Thu Nov 19 12:03:45.623195 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  23. NilPortugues\\Serializer\\Serializer->serializeData($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:458
[Thu Nov 19 12:03:45.623201 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  24. NilPortugues\\Serializer\\DeepCopySerializer->serializeObject($value = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:150
[Thu Nov 19 12:03:45.623207 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  25. NilPortugues\\Serializer\\Serializer->serializeInternalClass($value = *uninitialized*, $className = *uninitialized*, $ref = *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/DeepCopySerializer.php:34
[Thu Nov 19 12:03:45.623212 2015] [:error] [pid 20740] [client 10.0.0.70:50764] PHP  26. array_map(*uninitialized*, *uninitialized*) /var/www/WinStreamAPI/vendor/nilportugues/serializer/src/Serializer.php:458

@nilportugues
Copy link
Owner

This is a problem for Doctrine. It's design is flawed as it has circular references so it cannot be directly mapped. It will just blow up as you experienced.

I tried solving this issue, but it requires setting a magic nesting number that will vary from case to case, so I decided not to include this solution until I find a way of fixing this.

What I can recommend is creating objects to represent the resource that do not include so many references.

For instance for an object having a reference to a first entity that has another reference, try redefing the "deepest entity" by removing any relationship to its parents or further relationships to other entities.

@nilportugues
Copy link
Owner

If you or anyone reading this finds a solution, please post here

@nilportugues
Copy link
Owner

This is a known issue: symfony/symfony#15627

And Dunglas tried patching it symfony/serializer@aae6fa7. Still doesn't fix the issue.

I've got an idea on how to solve this, but I need some time to code it.

@dunglas
Copy link

dunglas commented Feb 21, 2016

Maybe can you try this trick to avoid circular references with Doctrine and display the entity's id when it is detected more than once: https://github.com/dunglas/DunglasApiBundle/blob/master/src/JsonLd/Serializer/ItemNormalizer.php#L63-L65

        $this->setCircularReferenceHandler(function ($object) {
            return $object->getId(); // It's better to use Doctrien metadata here to guess the id
        });

We use it in API Platform and it works fine.

@nilportugues
Copy link
Owner

@dunglas yeah I remember i send a tweet about it some months ago... just have to port it to my serializer, it's not JMS or Symfony's.

@AlexandreKilian
Copy link

Any news on this front? Or any orkarounds to make actual practical use of this? Because I really want to implement this

@nilportugues
Copy link
Owner

@AlexandreKilian for the time being, breaking the cyclic dependency is the only way around, and that can be done by transforming all doctrine entities to objects of your own...

I would need a day or two to dig into this properly, but this is a side project for me.

I'm not writing APIs right now on my daily basis so I cannot spend as much time as I'd like to fix this.

@AlexandreKilian
Copy link

@nilportugues Sorry, that came accross the wrong way... I might have an idea of how to easily work around this issue with a custom repository class, but I'm still working on a few kinks

@nilportugues
Copy link
Owner

@AlexandreKilian I'm actually trying to find myself some time to detect the cyclic dependencies and do something about it too.

I'll keep you posted.

@dkwavetech
Copy link

@nilportugues Hi while waiting your fixing, i delete manually the closure from the clone of my entity
Example : unset($cloneEntity->getContract()->initializer);

Another solution: I tried to add the fetch mode "EAGER" on my entities to avoid the "Proxy class" which add the Closures, but i get a 500 error response from your bundle (with a blank page)

Thank you !

@svparijs
Copy link

svparijs commented Jul 8, 2016

@nilportugues Has anyone got a temporary fix of some way to work around this issue expect creating additional object?

@nilportugues
Copy link
Owner

@svparijs you can create your DTOs and link them together manually and serialize that and the problem is gone.

Actually it's a good practise to do so.

@svparijs
Copy link

svparijs commented Jul 8, 2016

@nilportugues it feels like a extra level of complexity and maintenance cost to add DTO's manually wiring them together. To make this package properly usable for Symfony/Doctrine this feature should be supported in my opinion. That being said I've been digging around in the code and it seems not to be easily implemented.

I really would like this to work and would even be willing to sponsor a bit of the work.

@The-Don-Himself
Copy link

Can anybody post an example or gist of a hack on how to get around this? Would be greatly appreciated :)

@c0urg3tt3
Copy link

maybe using JsonSerializable in your entities you can
implements JsonSerializable
and define a
public function jsonSerialize()
that return the entity without the extra relashionship that cause the loop.

something like this gist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants