关于 PHP 序列化和反序列化不得不知道的细节 (待确认)

在开发
例如:下载中心导出的任务需要将处理类序列化到数据库,或者Redis
例如:队列任务需要将处理类序列化到 Redis 等
像如此常见的序列化操作,有很大几率出错是很正常的

我们定义两个类来测试

class A {
    protected $class;

    public function __construct($class) {
        $this->class = $class;
    }

    public function dd() {
        $this->class->d();
    }
}
class B {

    protected $x;
    protected $y;

    public function __construct($x, $y) {
        $this->x = $x;
        $this->y = $y;
    }

    public function d() {
        echo "Hello";
    }
}

我们需要这样子输出

  • 如果是直接传入 类属性 并且直接执行,那么是能够正常输出的
    $b = new B(1,2);
    $a = new A($b);
    $a->dd();

如果我们序列化呢?

  • 先在程序中序列化
    $a = serialize($a);
  • 然后序列化得到字符串
    O:1:"A":1:{s:8:" * class";O:1:"B":2:{s:4:" * x";i:1;s:4:" * y";i:2;}}
  • 然后我们在另外一个程序进行反序列化并且执行 $a->dd()
    $a = '<上面的序列化后的字符串,输入会导致格式显示问题,所以我就不输入了>';
    $a = unserialize($a);
    $a->dd();
  • 对的,你没看错,报错了,居然报错了!!!
    PS D:\data\文档> php a.php
    Fatal error: Uncaught Error: Call to a member function d() on null in D:\data\文档\a.php:11
    Stack trace:
    #0 D:\data\文档\a.php(31): A->dd()
    #1 {main}
    thrown in D:\data\文档\a.php on line 11

    结论

  • 在使用序列化的函数,允许对 类的继承 进行序列化 (大家可以去测试一下,是正常的)
  • 在使用序列化的函数,允许对 基本属性 进行序列化
  • 在使用序列化的函数,不允许 将别的类 传入到 类属性中 进行序列化
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 1

file

  • 在使用序列化的函数,不允许 将别的类 传入到 类属性中 进行序列化

这个问题应该是因为\x00这个字符串,复制粘贴的时候,丢失了,所以 unserialize() 返回了 null

4年前 评论
h6play (楼主) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!