Magento 2.2: Невозможно десериализовать значение?


33

Проблемы с сайтом под управлением Magento 2.2.0-rc3.0 / PHP 7.0.23

Следующая проблема возникает со всеми сторонними расширениями, включенными или отключенными.

При добавлении элемента к сравнению со страницы категории или продукта или при отправке отзыва со страницы продукта в браузере появляется следующая ошибка:

1 exception(s):
Exception #0 (InvalidArgumentException): Unable to unserialize value.

Exception #0 (InvalidArgumentException): Unable to unserialize value.
#0 /home/___/public_html/app/code/Magento/Theme/Controller/Result/MessagePlugin.php(157): Magento\Framework\Serialize\Serializer\Json->unserialize('[{\\"type\\":\\"su...')
#1 /home/___/public_html/app/code/Magento/Theme/Controller/Result/MessagePlugin.php(135): Magento\Theme\Controller\Result\MessagePlugin->getCookiesMessages()
#2 /home/___/public_html/app/code/Magento/Theme/Controller/Result/MessagePlugin.php(84): Magento\Theme\Controller\Result\MessagePlugin->getMessages()
#3 /home/___/public_html/lib/internal/Magento/Framework/Interception/Interceptor.php(146): Magento\Theme\Controller\Result\MessagePlugin->afterRenderResult(Object(Magento\Framework\View\Result\Page\Interceptor), Object(Magento\Framework\View\Result\Page\Interceptor), Object(Magento\Framework\App\Response\Http\Interceptor))
#4 /home/___/public_html/lib/internal/Magento/Framework/Interception/Interceptor.php(153): Magento\Framework\View\Result\Page\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Response\Http\Interceptor))
#5 /home/___/public_html/generated/code/Magento/Framework/View/Result/Page/Interceptor.php(26): Magento\Framework\View\Result\Page\Interceptor->___callPlugins('renderResult', Array, Array)
#6 /home/___/public_html/lib/internal/Magento/Framework/App/Http.php(139): Magento\Framework\View\Result\Page\Interceptor->renderResult(Object(Magento\Framework\App\Response\Http\Interceptor))
#7 /home/___/public_html/lib/internal/Magento/Framework/App/Bootstrap.php(256): Magento\Framework\App\Http->launch()
#8 /home/___/public_html/index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))
#9 {main}

Ошибка не исчезнет, ​​если вы не удалите файлы cookie, в частности, файлы cookie mage-messages. введите описание изображения здесь

Любая помощь в устранении этих ошибок приветствуется.


Разве это не основная ошибка? есть ли проблема GitHub для этого?
— Алекс

это даст вам представление о scommerce-mage.com/blog/...
— stevensagaar

Ответы:


60

Я смог решить эту проблему, очистив мой Redis Cache из CLI

redis-cli flushall

Надеюсь, это поможет будущим пользователям.


2
Красиво сделано. Вероятно, это должен быть принятый ответ.
— Шон Абрамсон,

Кажется, не всегда это решение. В моем случае я даже не использую redis (пока)
— Alex

Спасибо. Я перезапустил лак, думая, что смоет его, но это помогло.
— ladle3000

это работает для меня
— Джаред Чу

Это помогло мне при обновлении с 2.2.9 до 2.3.2. Я получил ошибку, когда я выполнил установку php bin / magento: upgrade;
— Мохаммед Джорайд

30

Проблема в /vendor/magento/framework/Serialize/Serializer/Json.php. Есть функция unserialize ($ string), которая выдает синтаксическую ошибку, если строка сериализуется (не json, а сериализация php).

Существует обходной путь - вы можете проверить, является ли строка сериализованной (против json-кодированной), а затем использовать serialize ($ string). Изменить десериализацию на:

public function unserialize($string)
{
    if($this->is_serialized($string))
    {
        $string = $this->serialize($string);
    }
    $result = json_decode($string, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
         throw new \InvalidArgumentException('Unable to unserialize value.');

    }
    return $result;
}

и добавьте функцию, чтобы проверить, сериализована ли строка:

function is_serialized($value, &$result = null)
{
    // Bit of a give away this one
    if (!is_string($value))
    {
        return false;
    }
    // Serialized false, return true. unserialize() returns false on an
    // invalid string or it could return false if the string is serialized
    // false, eliminate that possibility.
    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':
            // This looks odd but it is quicker than isset()ing
            $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;
}

После сохранения fe. категория без проблем, вы можете восстановить класс по умолчанию, и в будущем такой проблемы не будет.


1
Это работает на 100% хорошо для меня. Большое спасибо!
— Мапаладия

2
это не работает ... :-(
— Арфан Мирза

Проверьте, что произойдет, если передано значение a: 0: {}. Иди построчно. Что произойдет, если результат unserialize будет передан строго типизированному методу, который ожидает массив? Вы можете изменить свой ответ.
— vitoriodachef

20

Не редактируйте основные файлы для решения. Переопределить следующий путь Просто поместите следующую строку в di.xml внутри директории etc

<preference for="Magento\Framework\Serialize\Serializer\Json" type="Namespace\ModuleName\Serialize\Serializer\Json" />

И внутри пространства имен \ ModuleName \ Serialize \ Serializer Directory: файл Json.php

<?php
namespace Namespace\ModuleName\Serialize\Serializer;



class Json extends \Magento\Framework\Serialize\Serializer\Json
{


    /**
     * {@inheritDoc}
     * @since 100.2.0
     */
    public function unserialize($string)
    {
      if($this->is_serialized($string))
        {
            $string = $this->serialize($string);
        }
        $result = json_decode($string, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
             throw new \InvalidArgumentException('Unable to unserialize value.');

        }
        return $result;
    }


    function is_serialized($value, &$result = null)
    {
    // Bit of a give away this one
        if (!is_string($value))
        {
            return false;
        }
        // Serialized false, return true. unserialize() returns false on an
        // invalid string or it could return false if the string is serialized
        // false, eliminate that possibility.
        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':
                // This looks odd but it is quicker than isset()ing
                $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;
    }
}

Работает отлично


2
Реализация несовершенна. Что произойдет, если значение a: 0: {} будет передано методу Json: unserialize? Это желаемое поведение? Какой смысл в переменной результата в методе is_serialized? Он не возвращается и не влияет ни на что, поскольку при вызове метода никакая переменная не передается в качестве второго аргумента.
— vitoriodachef

Это должно быть приемлемым решением, и намного лучше, чем в посте выше, редактировать файл непосредственно у поставщика. Скорее всего, вам придется запускать задачу обновления установки локально, а затем снова в промежуточном / производственном режиме, так что ей придется сохранять среду, а каталог vendor / - это артефакт, созданный во время сборки.
— Марк Шуст

@vitoriodachef Я сталкиваюсь с конкретным случаем, о котором вы упомянули. Вы нашли какое-нибудь решение?
— Knight017

Я использовал следующую функцию для определения закрытой функции isSerialized ($ value) {return (boolean) preg_match ('/ ^ ((s | i | d | b | a | O | C): | N;) /', $ value ); }
— Knight017

Не работает Мне пришлось вручную изменить все записи в БД с a:0:{}на[]
— localhost

16

В моем случае я пропатчил следующим образом, чтобы десериализовать сериализованную строку: File: /vendor/magento/framework/Serialize/Serializer/Json.php

Найти:

public function unserialize($string)
{
    $result = json_decode($string, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new \InvalidArgumentException('Unable to unserialize value.');
    }
    return $result;
}

заменить на:

public function unserialize($string)
{
    $result = json_decode($string, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        if(false !== @unserialize($string)){
            return unserialize($string);
        }
        throw new \InvalidArgumentException('Unable to unserialize value.');
    }
    return $result;
}

Я пробовал это, но это не работает, как ожидалось. Кто-нибудь пробовал это, и если получилось, пожалуйста, помогите мне
— Шива

С какими проблемами вы столкнулись?
— MageLearner

Проблема исправлена. Спасибо за вопрос!
— Шива

1
Грт ... Спасибо !!!
— MageLearner

1
Спасибо @MageLearner, он также работает в 2.3.1 после переноса данных из magento 1 в magento 2
— Pradeep Thakur

5

После очистки Redis проблема разобралась. Спасибо Крейг за решение.

Я использую порт 6379 для кеша, поэтому я запускаю команду:

redis-cli -p 6379 flushall

4

В основном это связано с кэшем Redis, поэтому попробуйте сбросить это с помощью простой команды в вашем SSH

Redis-Cli Flushall


3

Это оказалось проблемой с разрешениями, когда magento настраивал разрешения для сгенерированных файлов, которые были ограничены на этом сервере.

Решается созданием файла magento_umask в корневом каталоге с соответствующим umask для сервера.

См. Http://devdocs.magento.com/guides/v2.2/install-gde/install/post-install-umask.html для получения дополнительной информации.


Здравствуйте, я сталкиваюсь с такой проблемой, как это. Можете ли вы посмотреть на это .
— Адитья шах

@chunk все мои каталоги - 755, а файлы - 644, какой подходящий umask установить? Тиа
— Крис Вэнь

2

Ответ Самирса выше работал для меня, хотя я должен был использовать другой код в блоке.

public function serialize($data)
{
    $result = json_encode($data);
    if (false === $result) {
        throw new \InvalidArgumentException('Unable to serialize value.');
    }
    return $result;
}

function is_serialized($value, &$result = null)
{
    // Bit of a give away this one
    if (!is_string($value))
    {
        return false;
    }
    // Serialized false, return true. unserialize() returns false on an
    // invalid string or it could return false if the string is serialized
    // false, eliminate that possibility.
    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':
            // This looks odd but it is quicker than isset()ing
            $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;
}

/**
 * {@inheritDoc}
 */
public function unserialize($string)
{
    if($this->is_serialized($string))
        {
        $result = $this->serialize($string);
        }
    $result = json_decode($string, true);

    return $result;
}

1

Корневой каталог 1. public_html/vendor/magento/framework/Serialize/Serializer/Json.php

Загрузить файл JSON.php https://gist.github.com/manojind/9f18bbecaeb3e2bbfb056a634ade62a2

2. Просто замените нижеприведенную функцию (unserialize) и добавьте новую функцию ИЛИ просто загрузите прикрепленный файл и замените его по умолчанию

public function unserialize($string)
{
    if($this->is_serialized($string))
    {
        $string = $this->serialize($string);
    }
    $result = json_decode($string, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
         throw new \InvalidArgumentException('Unable to unserialize value.');

    }
    return $result;
}

3. Добавить новую функцию:

function is_serialized($value, &$result = null)
{

    if (!is_string($value))
    {
        return 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':
                       $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;
} 

Моя проблема не решена .. пожалуйста, помогите мне
— Мухаммед Ахмед

1

Я лично обнаружил, что эта проблема возникла, когда он запускает команду:

php bin/magento setup:upgrade

После миграции. Я обнаружил, что мне не хватало ключа хеширования cryptsrc/app/etc/env.php :

<?php
return [
    'backend' => [
        'frontName' => 'admin'
    ],
    'crypt' => [
        'key' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    ],

    ...

Убедитесь, что он не пустой и предпочтительно соответствует другим условиям ваших проектов!


Я оставил ключ шифрования пустым во время установки, ожидая, что будет сгенерирован новый, что явно не происходит.
— Shapeshifter

0

Я получал сообщение об ошибке на странице CMS в передней части.

Это был код виджета Magento в содержимом страницы CMS, который вызывал проблему (которую я скопировал из другого источника). Я удалил код виджета и вставил тот же виджет с помощью кнопки «Вставить виджет» на экране редактирования страницы CMS, и это сработало.

Вышеуказанный процесс по-разному форматировал код виджета, и ошибка исчезла.


0

Я обнаружил, что все сериализованные данные не могут быть помещены в столбец таблицы MySQL с TEXTтипом данных.
Я только что нашел flag_dataзначение столбца system_config_snapshotстроки обрезается.

Я должен был изменить это MEDIUMTEXTдля этого столбца flag.flag_data.


0

Была такая же ошибка. При попытке обновить базу данных (версия 2.2.6) свежим кодом (версия 2.3.2).

Для исправления - работает

composer update

0

Это не лучший способ запустить sql напрямую, но я сделал это для экономии моего времени. Просто запустите этот запрос

ALTER TABLE flag MODIFY flag_data LONGTEXT;
UPDATE flag SET flag_data = '{"system":"","scopes":"","themes":""}' WHERE flag_code = 'config_hash';
UPDATE flag SET flag_data = '{}' WHERE flag_code = 'system_config_snapshot';

0

Если вы используете 2.3.0 или выше, вы можете использовать решение, предоставленное MageLearner. Более старый способ с заявлениями случая устарел. Если вы не используете решение MageLearner на 2.3.0 или выше; Вы столкнетесь со всевозможными проблемами с просмотром данных заказа и настраиваемых продуктов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.