Symfony升级后反序列化报错:__PHP_Incomplete_Class无反序列化器
解决Symfony升级后反序列化旧命名空间对象的问题
升级Symfony 3.3到6.1后出现Warning: Class __PHP_Incomplete_Class has no unserializer错误,本质是数据库里存的序列化数据用的是旧命名空间AppBundle,但代码里已经改成了新命名空间App\Controller\AppBundle,导致反序列化找不到对应类。下面是两种解决思路:
临时兼容方案(快速修复)
直接在getCart方法里给unserialize加类映射,把旧类名指向新类名,不用动数据库:
public function getCart() { return unserialize($this->cart, [ 'allowed_classes' => true, 'classmap' => [ 'AppBundle\Entity\Cart' => 'App\Controller\AppBundle\Entity\Cart', // 其他涉及旧命名空间的类也需要加在这里 ], ]); }
这个方案能立刻让项目正常运行,适合先解决紧急问题。
永久迁移方案(彻底解决)
写个Symfony命令脚本,批量把数据库里的旧命名空间序列化数据换成新的,步骤如下:
- 创建一个自定义Symfony命令,注入Doctrine的实体管理器;
- 查询所有包含
cart字段的实体记录; - 循环处理每条记录:反序列化旧数据、确保对象是新命名空间实例、重新序列化后存回数据库:
// 命令类示例代码 public function execute(InputInterface $input, OutputInterface $output) { $em = $this->getContainer()->get('doctrine.orm.entity_manager'); $orders = $em->getRepository(Order::class)->findAll(); // 假设是Order实体有cart字段 foreach ($orders as $order) { // 先临时用类映射反序列化旧数据 $cart = unserialize($order->getCart(), [ 'classmap' => ['AppBundle\Entity\Cart' => 'App\Controller\AppBundle\Entity\Cart'] ]); // 重新序列化新命名空间的对象 $order->setCart(serialize($cart)); } $em->flush(); $output->writeln('数据迁移完成'); return Command::SUCCESS; }
执行完这个命令后,数据库里的序列化数据就都用新命名空间了,之后可以把临时兼容的代码删掉。
后续优化建议
别再用PHP原生的serialize/unserialize了,换成JSON序列化(比如用Symfony的Serializer组件)。JSON不依赖类的命名空间,以后再改结构或命名空间都不会踩这个坑:
// 序列化时存JSON $this->cart = json_encode($cartObject); // 反序列化时转成对象或数组 return json_decode($this->cart, false); // false返回stdClass,true返回数组
内容的提问来源于stack exchange,提问作者Matthias Bakker
相关产品推荐
相关产品推荐

