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 від CLI

redis-cli flushall

Я сподіваюся, що це допоможе майбутнім користувачам.


2
Чудово зроблено. Це, мабуть, має бути прийнятою відповіддю.
Шон Абрамсон

Здається, не завжди це рішення. У моєму випадку я навіть не використовую redis (поки)
Alex

Спасибі. я перезапустив лак, думаючи, що його змиє, але це зробило трюк.
ladle3000

це працює для мене
Джаред Чу

Це допомогло мені підняти з 2.2.9 до 2.3.2. Я отримав помилку, коли виконував налаштування
Мохаммед Жораїд

30

Проблема полягає в /vendor/magento/framework/Serialize/Serializer/Json.php є функція unserialize ($ string), яка дає вам помилку в синтаксисі, якщо рядок серіалізований (не json, а php серіалізація).

Існує обхідне рішення - ви можете перевірити, чи рядок є серіалізованим (vs 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;
}

Після збереження фе. категорію без проблем. Ви можете відновити клас до замовчування, і такої проблеми в майбутньому не буде.


1
Це працює на 100% штрафу для мене. Дуже дякую!
mapaladiya

2
це не працює ... :-(
Арфан Мірза

Перевірте, що станеться, якщо передано значення a: 0: {}. Переходьте по рядку. Що станеться, якщо результат несеріалізації перейде до сильного набраного методу, який очікує масив? Ви можете змінити свою відповідь.
vitoriodachef

20

Не редагуйте основні файли для вирішення. Перезапис наступним способом Просто помістіть наступний рядок у каталог di.xml всередині тощо

<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

Це має бути прийнятим рішенням і набагато краще, ніж публікація вище, щоб редагувати файл безпосередньо у постачальника. Більше ніж, ймовірно, вам доведеться запустити завдання оновлення установки локально, а потім знову встановити / виготовити, тож доведеться зберігати середовища, а постачальник / каталог - це артефакт, створений під час збирання.
Марк Шуст

@vitoriodachef Я зіткнувся з точним випадком, який ви згадали. Ви знайшли якесь рішення?
Knight017

Я використовував наступну функцію, щоб визначити приватну функцію isSerialized ($ value) {return (boolean) preg_match ('/ ^ ((s | i | d | b | a | O | C): | N;) /', $ value ); }
Knight017

Не працює. Мені довелося вручну змінити всі записи в БД з a:0:{}на[]
localhost

16

У моєму випадку я промальовував наступне, щоб несеріалізувати серіалізовану рядок: Файл: /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
Grt ... Дякую !!!
MageLearner

1
Дякуємо @MageLearner, він також працює в 2.3.1 після перенесення даних з магенто 1 в магенто 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 встановити? tia
Кріс Вень

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

Каталог ROOT 1. public_html/vendor/magento/framework/Serialize/Serializer/Json.php

Завантажте JSON.php https://gist.github.com/manojind/9f18bbecaeb3e2bbfb056a634ade62a2

2. Просто замініть нижче функцію (несеріалізуйте) і додайте нову функцію АБО просто завантажте прикріплений файл і замініть за замовчуванням

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

Після міграції. Я дізнався, що мені не вистачає хеш-ключа " crypt " у src/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.