简单的PHP7.0类错误地序列化

时间:2017-05-10 17:05:25

标签: php symfony serialization doctrine php-7

我试图在PHP7.0中序列化一组简单对象,但由于某种原因它无法正常工作。以下是var_dump&n;对象数组:

array (size=3)
  0 => 
    object(My\Bundle\Entity\Role)[504]
      protected 'id' => int 2
      protected 'role' => string 'ROLE_LDAP_CHECKIN_APP_ADMIN' (length=27)
  1 => 
    object(My\Bundle\Entity\Role)[506]
      protected 'id' => int 3
      protected 'role' => string 'ROLE_LDAP_CHECKIN_APP_USER' (length=26)
  2 => 
    object(My\Bundle\Entity\Role)[507]
      protected 'id' => int 1
      protected 'role' => string 'ROLE_USER' (length=9)

这将输出以下序列化字符串:

a:3:{i:0;r:18;i:1;r:22;i:2;r:26;}

如果我反序列化该字符串,我只会收到以下错误:

Notice: unserialize(): Error at offset 14 of 33 bytes

该类实现\Serializiable

namespace My\Bundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Role Entity
 *
 * @ORM\Entity
 * @ORM\Table( name="role" )
 *
 */
class Role implements \Serializable
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer", name="id")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", name="role", unique=true, length=255)
     * @Assert\NotBlank()
     */
    protected $role;

    /**
     * Populate the role field
     * @param string $role ROLE_FOO etc
     */
    public function __construct($role)
    {
        $this->role = $role;
    }

    /**
     * Return the id field.
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set the role field
     *
     * @param $role
     */
    public function setRole($role)
    {
        $this->role = $role;
    }

    /**
     * Return the role field.
     * @return string
     */
    public function getRole()
    {
        return $this->role;
    }

    /**
     * Return the role field.
     * @return string
     */
    public function __toString()
    {
        return (string) $this->role;
    }

    public function serialize()
    {
        return serialize(array($this->id, $this->role));
    }

    public function unserialize($serialized)
    {
        list($this->id, $this->role) = unserialize($serialized);
    }
}

我可以确认正在加载该类。

编辑:根据http://www.phpinternalsbook.com/classes_objects/serialization.html,序列化字符串中的'r'条目代表'引用',表示该条目只是指向其他条目的引用/指针在数组或对象中。显然,对第18,22和26条的引用毫无意义。这是一个PHP错误吗?

1 个答案:

答案 0 :(得分:0)

我在问题编写中没有提到这一点,但我在包装类'serialize函数中调用了序列化函数。换句话说,子类具有serialize函数,在其中调用parent::serialize,我试图在嵌套父类serialize函数内序列化我的数组。虽然不是未定义的行为,但这是PHP中的一个已知错误(是的,它有时实际上不是你的错)。此处列出了错误:https://bugs.php.net/bug.php?id=66052&edit=1

错误报告中的一些摘录:

  

当前序列化格式未指定值ids,而是依赖于数据开头的计数。虽然这适用于“标准”序列化,但当自定义序列化(通过Serializable)投入混合时,它会破坏性。

......和......

  

这个错误的影响是两件事之一:

     
      
  • 这些值只是指向错误的变量。对于不熟悉序列化格式的人来说,很难调试并且令人难以置信的混淆。
  •   
  • 值指向不存在的值(-1或最大+1)。这会导致错误,该错误会将字节偏移量报告给发生错误的序列化数据。
  •   

这解释了为什么问题中显示的序列化字符串中的引用被打破了。我不知道如何解决这个问题,除了手动扁平化所有序列化调用之外,我很惊讶它还没有得到那些从事PHP工作的优秀人员的解决。无论如何,如果您看到关于字符串/缓冲区的字节偏移的看似无法解释的错误消息,那么请确保您没有进行自定义嵌套序列化。