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.

Futter
quelle
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.

Craig
quelle
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.

Edmund
quelle
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

Sameer Bhayani
quelle
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;
}
MagierLerner
quelle
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
Praveen P. Rokade
quelle
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

Tahir Iqbal Najam
quelle
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 .

Futter
quelle
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;
}
Adam Jackson
quelle
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;
} 
mnojind
quelle
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!

Chris Rogers
quelle
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.

Binod
quelle
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.

Kirby
quelle
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
Alex
quelle
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';
gh darvishani
quelle
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.

Andy
quelle