浏览文章

文章信息

Magento2 Unable to unserialize value. 12745

1、说明

因为Magento核心文件在序列化的类中未加入验证是否已经序列化的检测,所以,如果你使用的第三方扩展未适配Magento2.x更高级的版本就会出现此问题。


2、解决

解决方式有两种,第一种则是推荐的方式。

方法一:修改所有扩展中的json_encode,使用Magento框架核心类序列化保存。


方法二:暴力解决,直接修改核心文件。

注意:更改核心文件是很不科学的事情,但是有时候为了“有效率的”解决问题,没办法。

修改核心文件: /vendor/magento/framework/Serialize/Serializer/Json.php

第36行

/**
* @inheritDoc
* @since 101.0.0
*/
public function unserialize($string)
{
   /** 添加判断是否已经序列化检查 START */
   if ($this->is_serialized($string)) {
       $string = $this->serialize($string);
   }
   /** 添加判断是否已经序列化检查 END */
   $result = json_decode($string, true);
   if (json_last_error() !== JSON_ERROR_NONE) {
       throw new \InvalidArgumentException("Unable to unserialize value. Error: " . json_last_error_msg());
   }
   return $result;
}

添加完以上代码后,47行添加上面代码提到的函数is_serialized


/**
* 检查是否已经序列化
* @param $value
* @param null $result
* @return bool
*/
function is_serialized($value, &$result = null)
{
   // 非字符串滚开
   if (!is_string($value)) {
       return false;
   }
   /**
    * 序列化为false,返回true。
    * unserialize()对无效字符串返回false,
    * 或者如果字符串被序列化为false,则可能返回false,消除这种可能性。
    */
   if ($value === 'b:0;') {
       $result = false;
       return true;
   }
   $length = strlen($value);
   $end = '';
   switch ($value[0]) {
       case 's':
           if ($value[$length - 2] !== '"') {
               return false;
           }
       case 'b':
       case 'i':
       case 'd':
           // 看起来很奇怪,但比isset()要快的写法
           $end .= ';';
       case 'a':
       case 'O':
           $end .= '}';
           if ($value[1] !== ':') {
               return false;
           }
           switch ($value[2]) {
               case 0:
               case 1:
               case 2:
               case 3:
               case 4:
               case 5:
               case 6:
               case 7:
               case 8:
               case 9:
                   break;
               default:
                   return false;
           }
       case 'N':
           $end .= ';';
           if ($value[$length - 1] !== $end[0]) {
               return false;
           }
           break;
       default:
           return false;
   }
   if (($result = @unserialize($value)) === false) {
       $result = null;
       return false;
   }
   return true;
}



原创