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

Fix composite key serialization #167

Open
wants to merge 2 commits into
base: 1.5.x
Choose a base branch
from

Conversation

ddeboer
Copy link

@ddeboer ddeboer commented Jan 12, 2015

Currently, calling unserialize() with some data previously returned from serialize() produces:

Array to string conversion

/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2913

This is caused by serialize() incorrectly serializing entities with primary keys (on doctrine/orm 2.4.):

"ref1":["Entity\\MyEntity",{"user":{"__initializer__":{},"__cloner__":{},"__isInitialized__":false},"somethingElse":{"__initializer__":null,"__cloner__":null,"__isInitialized__":true}}]

This seems to be caused by the identifier lookup for $simpleReferences not working properly. For each object constituting the composite key, it returns the object itself instead of its id. E.g.:

array(2) {
  [0] =>
  string(38) "Entity\MyEntity"
  [1] => 
    'user' =>
    class Proxies\__CG__\Entity\User#4711 (25) {
        // ...
    },
    'somethingElse' =>
    class Proxies\__CG__\Entity\SomethingElse#1234 (25) {
        // ...
    }

By adding a getReference() the identifier lookup works correctly. It now looks at $this->identities first, which holds the correct composite identities. Of course, the extra call does have a slight performance impact:

array(2) {
  [0] =>
  string(38) "Entity\MyEntity"
  [1] =>
  array(3) {
    'user' =>
    int(4)
    'somethingElse' =>
    int(1)
  }
}

@ddeboer
Copy link
Author

ddeboer commented Jan 13, 2015

This may be a (partial) fix for #135.

@lavoiesl lavoiesl added this to the 1.1 milestone Mar 22, 2015
@lavoiesl
Copy link
Member

Can you provide tests for that?

@lavoiesl
Copy link
Member

@ddeboer, also, please rebase your commits.

@lavoiesl
Copy link
Member

@ddeboer, I would like to be able to release this PR in 1.1 by tomorrow, do you think you would be able to care of it?

@ddeboer ddeboer force-pushed the fix-composite-key-serialize branch 2 times, most recently from 6367b08 to a804012 Compare March 26, 2015 10:24
@ddeboer
Copy link
Author

ddeboer commented Mar 26, 2015

Rebased. Now working out how I can test this.

Btw, the original issue description is not wholly accurate any more after using the solution from #135.

@ddeboer ddeboer force-pushed the fix-composite-key-serialize branch from 29a15f5 to b4707b6 Compare March 26, 2015 13:45
@@ -22,7 +22,6 @@
use Doctrine\Common\DataFixtures\ProxyReferenceRepository;
use Doctrine\Common\DataFixtures\Event\Listener\ORMReferenceListener;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Proxy\Proxy;
Copy link
Author

Choose a reason for hiding this comment

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

Was unused.

@ddeboer ddeboer force-pushed the fix-composite-key-serialize branch from b4707b6 to ef54844 Compare March 26, 2015 13:47
@ddeboer
Copy link
Author

ddeboer commented Mar 26, 2015

Done.

@lavoiesl
Copy link
Member

Awesome! Thank you.

// themselves have a composite primary key are unsupported.
$proxyId = $this->getIdentifier($value, $uow);
$keys = array_keys($proxyId);
$values[$key] = $proxyId[$keys[0]];
Copy link
Member

Choose a reason for hiding this comment

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

Sorry if I’m misunderstanding something, but wouldn’t this create ID collisions? Why not use implode('|', $proxyId)?

Copy link
Author

Choose a reason for hiding this comment

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

In most cases, where the related entity has a single (not composite) primary key, count($proxyId) === 1.

Imploding the keys is an option, but unfortunately won’t help much. When the references are unserialized, references are retrieved from the entity manager. However, Doctrine does not support something like:

$roleRef = $em->getReference(self::TEST_ENTITY_USER_ROLE, [
    'role' => 1,
    'user' => [    // Doctrine doesn’t like this nested composite key
        'id' => 1,
        'code' => '007'
    ]
]);

@lavoiesl
Copy link
Member

After having carefully considered this PR and asked other guys on the Doctrine team, we won’t be accepting it as is. Before releasing support for composite keys, it will need to support all cases and/or have tests for all those.

I will reschedule this PR for 1.2 and will come back when I have a better understanding.

Thanks again.

@lavoiesl lavoiesl modified the milestones: 1.2, 1.1 Mar 28, 2015
@ddeboer
Copy link
Author

ddeboer commented Mar 29, 2015

I too prefer full support for nested composite keys, but as this requires changes in Doctrine itself I think starting simple, with support for unnested primary keys, is the way to go. Why does the solution have to tackle all cases at once? Why not work on a solution iteratively?

@Ocramius Ocramius modified the milestone: 1.2 Jun 19, 2016
@ddeboer ddeboer force-pushed the fix-composite-key-serialize branch 2 times, most recently from 66891de to 0db2c74 Compare November 11, 2019 07:48
Base automatically changed from master to 1.5.x January 23, 2021 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants