浏览文章
文章信息
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;
}