Magento 2.2: Wert kann nicht unserialisiert werden?


33

Probleme auf einer Site mit Magento 2.2.0-rc3.0 / PHP 7.0.23

Das folgende Problem tritt bei allen aktivierten oder deaktivierten Erweiterungen von Drittanbietern auf.

Beim Hinzufügen eines Artikels zum Vergleich von einer Kategorie oder Produktseite oder beim Senden einer Bewertung von einer Produktseite wird der folgende Fehler im Browser angezeigt:

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}

Der Fehler verschwindet erst, wenn Sie Cookies löschen, insbesondere das Cookie mage-messages. Bildbeschreibung hier eingeben

Hilfe bei der Behebung dieser Fehler wird gebeten.


Ist das nicht ein Kernfehler? Gibt es dafür ein GitHub-Problem?
Alex

Dies gibt Ihnen eine Idee scommerce-mage.com/blog/…
stevensagaar

Antworten:


59

Ich konnte dieses Problem beheben, indem ich meinen Redis-Cache über die CLI geleert habe

redis-cli flushall

Ich hoffe das hilft zukünftigen Usern.


2
Schön gemacht. Dies sollte wahrscheinlich die akzeptierte Antwort sein.
Shawn Abramson

Es scheint nicht immer die Lösung zu sein. In meinem Fall verwende ich (noch) nicht einmal Redis
Alex

Vielen Dank. Ich habe den Lack neu gestartet und dachte, das würde ihn spülen, aber das hat den Trick getan.
ladle3000

es funktioniert für mich
Jared Chu

Dies hat mir beim Upgrade von 2.2.9 auf 2.3.2 geholfen. Ich habe den Fehler erhalten, als ich das PHP- Bin / Magento-Setup ausgeführt habe: upgrade;
Mohammed Joraid

30

Das Problem ist, dass in /vendor/magento/framework/Serialize/Serializer/Json.php eine Funktion unserialize ($ string) vorhanden ist, die einen Syntaxfehler ausgibt, wenn der String serialisiert ist (nicht json, sondern php serialization).

Es gibt eine Problemumgehung: Sie können überprüfen, ob der String serialisiert ist (im Gegensatz zu json-codiert), und dann serialisieren ($ string). Ändern Sie unserialize in:

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;
}

und füge eine Funktion hinzu, um zu überprüfen, ob der String serialisiert ist:

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;
}

Nach dem Speichern z. Kategorie ohne Problem, Sie können Klasse auf Standard wiederherstellen und es wird kein solches Problem in Zukunft geben.


1
Es funktioniert 100% gut für mich. Vielen Dank!
Mapaladiya

2
es funktioniert nicht ... :-(
Arfan Mirza

Überprüfen Sie, was passiert, wenn der Wert a: 0: {} übergeben wird. Gehe Zeile für Zeile. Was passiert, wenn das Ergebnis von unserialize an eine stark typisierte Methode übergeben wird, die ein Array erwartet? Vielleicht möchten Sie Ihre Antwort ändern.
Vitoriodachef

20

Bearbeiten Sie keine Kerndateien zur Lösung. Override following way Füge einfach die folgende Zeile in die Datei di.xml im Verzeichnis etc ein

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

Und im Namespace \ ModuleName \ Serialize \ Serializer-Verzeichnis: Datei 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;
    }
}

Funktioniert perfekt


2
Die Implementierung ist fehlerhaft. Was passiert, wenn der Wert a: 0: {} an die Methode Json: unserialize übergeben wird? Ist es das gewünschte Verhalten? Wozu dient die Ergebnisvariable in der Methode is_serialized? Es wird nicht zurückgegeben und hat keinen Einfluss auf irgendetwas, da beim Methodenaufruf keine Variable als zweites Argument übergeben wird.
Vitoriodachef

Dies sollte die akzeptierte Lösung sein und ist viel besser als der obige Beitrag, um die Datei direkt im Anbieter zu bearbeiten. Es ist mehr als wahrscheinlich, dass Sie die Setup-Upgrade-Aufgabe lokal und dann erneut auf Staging / Production ausführen müssen, damit Umgebungen erhalten bleiben und Anbieter / Verzeichnis ein Artefakt ist, das zum Zeitpunkt der Erstellung erstellt wird.
Mark Shust

@vitoriodachef Ich stehe vor dem genauen Fall, den Sie erwähnt haben. Haben Sie eine Lösung gefunden?
Knight017

Ich habe die folgende Funktion verwendet, um zu entscheiden, ob die private Funktion isSerialized ($ value) {return (boolean) preg_match ('/ ^ ((s | i | d | b | a | O | C): | N;) /', $ value ist ); }
Knight017

Funktionierte nicht. Ich musste von Hand alle Einträge in der DB ändern von a:0:{}bis[]
localhost

16

In meinem Fall habe ich wie folgt gepatcht, um einen serialisierten String zu unserialisieren: File: /vendor/magento/framework/Serialize/Serializer/Json.php

Finden:

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;
}

ersetzt durch:

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;
}

Ich habe es versucht, aber es funktioniert nicht wie erwartet. Hat jemand dies versucht und wenn es funktioniert, bitte helfen Sie mir
Siva

Vor welchen Problemen standen Sie?
MageLearner

Das Problem wurde behoben. Danke für die Frage!
Siva

1
Grt ... Danke !!!
MageLearner

1
Danke @MageLearner, es funktioniert auch in 2.3.1 nach der Migration der Daten von Magento 1 nach Magento 2
Pradeep Thakur

5

Nach dem Spülen von Redis hat sich das Problem sortiert. Vielen Dank, Craig für die Lösung.

Ich verwende Port 6379 für den Cache und führe den folgenden Befehl aus:

redis-cli -p 6379 flushall

4

Dies hängt hauptsächlich mit dem Redis-Cache zusammen. Versuchen Sie also, dies mit einem einfachen Befehl in Ihrem SSH zu löschen

redis-cli flushall


3

Es stellte sich heraus, dass es sich um ein Berechtigungsproblem handelte, bei dem Magento Berechtigungen für generierte Dateien festlegte, die auf diesem Server beschränkt waren.

Lösung durch Erstellen einer magento_umask-Datei im Stammverzeichnis mit der entsprechenden umask für den Server.

Weitere Informationen finden Sie unter http://devdocs.magento.com/guides/v2.2/install-gde/install/post-install-umask.html .


Hallo, ich stehe dem damit verbundenen Problem so gegenüber. Können Sie in schauen Sie bitte diese .
Aditya Shah

@chunk alle meine dir sind 755, und Dateien sind 644, was ist die richtige umask zu setzen? tia
Kris Wen

2

Die Antwort von Sameers oben hat bei mir funktioniert, obwohl ich im Block anderen Code verwenden musste.

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

Wurzelverzeichnis 1. public_html/vendor/magento/framework/Serialize/Serializer/Json.php

Laden Sie JSON.php https://gist.github.com/manojind/9f18bbecaeb3e2bbfb056a634ade62a2 herunter

2. Ersetzen Sie einfach die unten stehende Funktion (unserialize) und fügen Sie eine neue Funktion hinzu ODER laden Sie einfach die angehängte Datei herunter und ersetzen Sie sie durch die Standardfunktion

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. Neue Funktion hinzufügen:

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;
} 

Mein Problem wurde nicht behoben. Bitte helfen Sie mir
Muhammad Ahmed

1

Ich persönlich fand dieses Problem großartig, da es den Befehl ausführt:

php bin/magento setup:upgrade

Nach einer Migration. Ich habe herausgefunden, dass mir der Hash-Schlüssel " crypt " fehlt in src/app/etc/env.php:

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

    ...

Stellen Sie sicher, dass dies nicht leer ist und vorzugsweise zu den anderen Umgebungen Ihrer Projekte passt!


Ich habe den Kryptoschlüssel während der Installation leer gelassen und erwartet, dass ein neuer generiert wird, was offensichtlich nicht der Fall ist.
Shapeshifter

0

Ich habe den Fehler auf einer CMS-Seite im Frontend erhalten.

Es war der Magento-Widget-Code im CMS-Seiteninhalt, der das Problem verursachte (den ich aus einer anderen Quelle kopiert habe). Ich habe den Widget-Code gelöscht und dasselbe Widget über die Schaltfläche Widget einfügen im Bearbeitungsbildschirm der CMS-Seite eingefügt, und es hat funktioniert.

Der obige Prozess hat den Widget-Code anders formatiert und den Fehler behoben.


0

Ich fand heraus, dass ganze serialisierte Daten nicht in eine MySQL-Tabellenspalte mit TEXTDatentyp passen .
Ich habe gerade festgestellt, dass der Spaltenwert flag_datader system_config_snapshotZeile abgeschnitten ist.

Ich musste es MEDIUMTEXTfür diese Spalte ändern flag.flag_data.


0

War der selbe Fehler. Beim Versuch, die Datenbank (Version 2.2.6) mit neuem Code (Version 2.3.2) zu aktualisieren.

Zum fixen Laufen

composer update

0

Dies ist nicht der beste Weg, um SQL direkt auszuführen, aber ich habe das getan, um meine Zeit zu sparen. Führen Sie einfach diese Abfrage aus

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

Wenn Sie Version 2.3.0 oder höher verwenden, möchten Sie die von MageLearner bereitgestellte Lösung verwenden. Der ältere Weg mit case-Anweisungen ist überholt. Wenn Sie die MageLearner-Lösung nicht für 2.3.0 oder höher verwenden; Sie werden auf alle möglichen Probleme stoßen, wenn Sie Auftragsdaten und konfigurierbare Produkte anzeigen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.