Skip to content

Loading…

DCOM-175: Proxies return private properties in __sleep, which is not supported by PHP. #477

Closed
doctrinebot opened this Issue · 8 comments

2 participants

@doctrinebot

Jira issue originally created by user bittarman:

sleep should not return private parent property names (see http://php.net/sleep) this raises notices, and also results in the value of the property being 'N' (null) instead of keeping its value.

I am unfortunately stuck having to serialize proxies in my revision tracking, as doctrine seems to be currently ignoring the fetch="EAGER" I set on the related properties.

Proxies should use the Serializable interface, and not **sleep, or not return parent property names which are private, it serves no purpose, and is not supported by PHP itself anyway.

Also, if you keep _sleep, but do not return the parent property names, then it will only include the items you return, so it would be better to simply drop the _sleep method, I cannot actually see any useful purpose it serves.

@doctrinebot

Comment created by bittarman:

just updated the issue body, realised that I worded something badly.

@doctrinebot

Comment created by @ocramius:

[~bittarman] I think that's a limitation we have. We use **sleep to avoid serializing fields like the initializers and the persisters of course.

Even by implementing serializable, it would only work if the end user implemented it in the parent class.

Tempted to mark it as "can't fix"

@doctrinebot

Comment created by @ocramius:

I think there's a solution by having something like following:

class SomeGeneratedProxyName extends RealName implements \Serializable
{
    public function unserialize($data)
    {
        $reflectionClass = new ReflectionClass($this);
        foreach ($reflectionClass->getProperties(ReflectionProperty::IS_PRIVATE) as $privateProp) {
            $privateProp->setAccessible(true);
            $privateProp->setValue($this, $data[$privateProp->getName()]);
        }
        // ... other props ...
    }

    public function serialize()
    {
        $data = array();
        $reflectionClass = new ReflectionClass($this);
        foreach ($reflectionClass->getProperties(ReflectionProperty::IS_PRIVATE) as $privateProp) {
            $privateProp->setAccessible(true);
            $data[$privateProp->getName()] = $privateProp->getValue($this);
        }
        // ... other props ...
        return $data;
    }
}
@doctrinebot

Comment created by @ocramius:

[~bittarman] I started implementing this one at https://github.com/Ocramius/common/compare/hotfix;[DCOM-175](http://www.doctrine-project.org/jira/browse/DCOM-175) and so far it looks promising.

The only doubts so far are with handling cases like following:

class MyEntity implements Serializable
{
    public function serialize()
    {
        // [...]
    }

    public function unserialize($serialized)
    {
        // [...]
    }

    public function **sleep()
    {
        // [...]
    }

    public function **wakeup()
    {
        // [...]
    }
}

So far I didn't get to write tests that demonstrate the exact behaviour for this case, but it looks like when Serializable is implemented, *_sleep and _*wakeup are ignored. Any thoughts on this?

@doctrinebot

Comment created by @ocramius:

A possible solution is to use something like http://eval.in/16806, and thus exploiting the ability of php to retrieve an object's private properties by using the special

chr(0) . 'Foo' . chr(0) . 'bar'

trick.

This can be abstracted by using

array_keys((array) $object);, which retrieves also those special keys

@doctrinebot

Comment created by @ocramius:

Provided a fix at #284

@doctrinebot

Comment created by @ocramius:

Solved at 9c6b861

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added the Bug label
@Ocramius Ocramius was assigned by doctrinebot
@doctrinebot doctrinebot added this to the 2.5.0 milestone
@doctrinebot doctrinebot closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.