Magento 2.2: Nie można oddzielić wartości?


33

Występują problemy w witrynie z Magento 2.2.0-rc3.0 / PHP 7.0.23

Następujący problem występuje w przypadku wszystkich rozszerzeń innych firm, które są włączone lub wyłączone.

Podczas dodawania elementu do porównania ze strony kategorii lub produktu lub przesyłania recenzji ze strony produktu pojawia się następujący błąd w przeglądarce:

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}

Błąd nie zniknie, chyba że usuniesz pliki cookie, w szczególności plik cookie wiadomości magów. wprowadź opis zdjęcia tutaj

Doceniamy wszelką pomoc w rozwiązywaniu tych błędów.


Czy to nie jest podstawowy błąd? czy jest z tym problem GitHub?
Alex

Odpowiedzi:


60

Udało mi się rozwiązać ten problem, opróżniając pamięć podręczną Redis z interfejsu CLI

redis-cli flushall

Mam nadzieję, że pomoże to przyszłym użytkownikom.


2
Ładnie wykonane. To prawdopodobnie powinna być zaakceptowana odpowiedź.
Shawn Abramson

Wydaje się, że nie zawsze jest to rozwiązanie. W moim przypadku nawet nie używam redis (jeszcze)
Alex

dzięki. ponownie uruchomiłem lakier, myśląc, że go spłucze, ale to załatwiło sprawę.
ladle3000

to działa dla mnie
Jared Chu

Pomogło mi to podczas aktualizacji z 2.2.9 do 2.3.2. Wystąpił błąd po uruchomieniu instalacji
Mohammed Joraid

30

Problem jest w /vendor/magento/framework/Serialize/Serializer/Json.php istnieje funkcja unserialize ($ string), która daje błąd składniowy, jeśli ciąg jest szeregowany (nie serializacja json, ale php).

Istnieje obejście - możesz sprawdzić, czy ciąg jest serializowany (w porównaniu z kodowaniem json), a następnie użyj serializacji ($ string). Zmień unserialize na:

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

i dodaj funkcję, aby sprawdzić, czy ciąg jest serializowany:

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

Po zapisaniu fe. kategoria bez problemu, możesz przywrócić klasę do wartości domyślnych i nie będzie takiego problemu w przyszłości.


1
Dla mnie działa w 100% w porządku. Wielkie dzięki!
mapaladiya

2
to nie działa ... :-(
Arfan Mirza

Sprawdź, co się stanie, jeśli wartość a: 0: {} zostanie przekazana. Idź linia po linii. Co się stanie, jeśli wynik odserializacji zostanie przekazany do metody o silnym typie, która oczekuje tablicy? Możesz zmienić swoją odpowiedź.
vitoriodachef

20

Nie edytuj podstawowych plików rozwiązania. Zastąp następujący sposób Wystarczy wstawić następujący wiersz do di.xml w katalogu etc

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

I wewnątrz Namespace \ ModuleName \ Serialize \ Serializer Directory: plik 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;
    }
}

Działa świetnie


2
Wdrożenie jest wadliwe. Co się stanie, jeśli wartość a: 0: {} zostanie przekazana do metody Json: unserialize? Czy to pożądane zachowanie? Jaki jest sens zmiennej wynikowej w metodzie is_serialized? Nie jest zwracane i nie ma wpływu na nic, ponieważ w wywołaniu metody żadna zmienna nie jest przekazywana jako drugi argument.
vitoriodachef

To powinno być zaakceptowane rozwiązanie i jest znacznie lepsze niż powyższy post, aby edytować plik bezpośrednio u dostawcy. Najprawdopodobniej będziesz musiał uruchomić zadanie aktualizacji instalatora lokalnie, a następnie ponownie na etapie przemieszczania / produkcji, więc będzie musiał zachować środowiska, a katalog dostawcy / jest artefaktem tworzonym podczas kompilacji.
Mark Shust

@vitoriodachef Mam do czynienia z dokładnie wspomnianą sprawą. Czy znalazłeś jakieś rozwiązanie?
Knight017,

Użyłem następującej funkcji, aby zdecydować, że funkcja prywatna jestSerialized (wartość $) {return (boolean) preg_match ('/ ^ ((s | i | d | b | a | O | C): | N;) /', $ value ); }
Knight017,

Nie działa. Musiałem ręcznie zmienić wszystkie wpisy w DB z a:0:{}na[]
localhost

16

W moim przypadku poprawiłem w następujący sposób, aby odserializować serializowany ciąg: Plik: /vendor/magento/framework/Serialize/Serializer/Json.php

Odnaleźć:

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

zastąpiony przez:

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

Próbowałem tego, ale nie działa zgodnie z oczekiwaniami. Czy ktoś próbował tego i jeśli to działa, proszę o pomoc
Siva

Jakie masz problemy?
MageLearner

Problem został rozwiązany. Dzięki, że pytasz!
Siva

1
Grt ... dziękuję !!!
MageLearner

1
Dzięki @MageLearner, Działa również w 2.3.1 po migracji danych z magento 1 do magento 2
Pradeep Thakur

5

Po opróżnieniu Redis problem został rozwiązany. Dziękuję Craig za rozwiązanie.

Używam portu 6379 do pamięci podręcznej, więc uruchamiam polecenie:

redis-cli -p 6379 flushall

4

Jest to głównie związane z pamięcią podręczną Redis, więc spróbuj wypróżnić to za pomocą prostej komendy w SSH

redis-cli flushall


3

Okazało się, że jest to problem z uprawnieniami, w którym magento ustawia uprawnienia do generowanych plików, które zostały ograniczone na tym serwerze.

Rozwiązany przez utworzenie pliku magento_umask w katalogu głównym z odpowiednim umask dla serwera.

Dodatkowe informacje można znaleźć na stronie http://devdocs.magento.com/guides/v2.2/install-gde/install/post-install-umask.html .


Witam, mam do czynienia z podobnym problemem w ten sposób. Czy możesz zajrzeć do tego .
Aditya Shah

@ chunk wszystkie moje katalog to 755, a pliki to 644, jaki jest odpowiedni umask do ustawienia? tia
Kris Wen

2

Powyższa odpowiedź Sameers działała dla mnie, chociaż musiałem użyć innego kodu w bloku.

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

Katalog ROOT 1. public_html/vendor/magento/framework/Serialize/Serializer/Json.php

Pobierz JSON.php https://gist.github.com/manojind/9f18bbecaeb3e2bbfb056a634ade62a2

2. Po prostu zamień poniżej funkcji (odserializuj) i dodaj nową funkcję LUB po prostu pobierz załączony plik i zamień na domyślny

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. Dodaj nową funkcję:

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

Mój problem nie został rozwiązany ... proszę mi pomóc
Muhammad Ahmed

1

Osobiście zauważyłem, że ten problem został rozwiązany, ponieważ głowa uruchomiła polecenie:

php bin/magento setup:upgrade

Po migracji. Dowiedziałem się, że brakuje mi klucza mieszającego „ crypt ” w src/app/etc/env.php:

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

    ...

Upewnij się, że nie jest pusty i najlepiej pasuje do innych środowisk twojego projektu!


Podczas instalacji zostawiłem pusty klucz szyfrujący, oczekując wygenerowania nowego, co oczywiście nie nastąpi.
Zmiennokształtny

0

Wystąpił błąd na stronie CMS w interfejsie użytkownika.

Problemem był kod widgetu Magento w treści strony CMS (który skopiowałem z innego źródła). Usunąłem kod widżetu i wstawiłem ten sam widżet za pomocą przycisku Wstaw widżet na ekranie edycji strony CMS i zadziałało.

Powyższy proces sformatował kod widgetu inaczej i spowodował, że błąd zniknął.


0

Dowiedziałem się, że całych danych zserializowanych nie można dopasować do kolumny tabeli MySQL bazy TEXTdanych o typie danych.
Właśnie odkryłem, że flag_datawartość kolumny system_config_snapshotlinii jest przycięta.

Musiałem to zmienić MEDIUMTEXTna tę kolumnę flag.flag_data.


0

Był ten sam błąd. Podczas próby aktualizacji bazy danych (wersja 2.2.6) świeżym kodem (wersja 2.3.2).

Dla poprawek uruchomionych

composer update

0

To nie jest najlepszy sposób na bezpośrednie uruchamianie sql, ale zrobiłem to dla zaoszczędzenia czasu. Po prostu uruchom to zapytanie

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

Jeśli korzystasz z wersji 2.3.0 lub nowszej, będziesz chciał skorzystać z rozwiązania dostarczonego przez MageLearner. Starsza metoda z użyciem instrukcji case jest przestarzała. Jeśli nie korzystasz z rozwiązania MageLearner w wersji 2.3.0 lub nowszej; napotkasz różnego rodzaju problemy z przeglądaniem danych zamówienia i produktów konfigurowalnych.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.