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.