PHP: 如何防止序列化命中某个成员

PHP: How to prevent serialize from hitting a certain member

我有一个用户对象,其受保护的成员指向一个 PDO 对象。

我正在使用 Silex/Symfony,当我尝试登录时 Symfony\Component\Security\Core\Authentication\Token\AbstractToken 开始序列化该对象并给出异常,因为 PDO 对象无法序列化。

我尝试将成员设为私有,但这没有帮助。如果我取消设置 __sleep 中的 属性 我不确定如何将它放回 __wakeup 中,因为该成员是通过在构造函数中传递来设置的。

我见过的示例通过静态查找取回不可序列化的内容,但我正在努力避免这种情况。有什么想法吗?

您需要对您的用户对象实施 Serializable

class User implements UserInterface, Serializable
{
    // ...

    public function serialize()
    {
        // see http://php.net/manual/en/serializable.serialize.php
        return serialize(array(
            $this->id,
            $this->username,
            $this->password
        ));
    }

    public function unserialize($serialized)
    {
        // see http://php.net/manual/en/serializable.unserialize.php
        list ($this->id, $this->username, $this->password) = unserialize($serialized);
    }
}

编辑

警告:此答案仅针对问题“如何防止序列化命中某个成员”。如果你发现自己有类似的问题,那么你应该重新考虑你在做什么。详情请看@Bryan Agee 的回答。

听起来你的模型对象中有持久化逻辑,这是你问题的真正根源;您可能想看看存储库设计模式来解决这个问题。

与此同时,重新填充该 PDO 对象的唯一真正选择是使用邪恶的全局变量;你的 __wakeup() 必须伸手去拿一个实例。

我想你也可以覆盖加载用户的服务,并将其替换为在反序列化后立即注入数据库的服务,但这似乎有点毛茸茸——最好只是从模型中提取持久性代码,并且只序列化模型。

一个小的补充:JMS Serializer 是一个很酷的 symfony 包,它允许你在你的实体中做注释,精确地选择你想要序列化(或不序列化)的 property/method。

查看: http://jmsyst.com/bundles/JMSSerializerBundle#usage