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.