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.

Głaskanie pod brodę
źródło
Czy to nie jest podstawowy błąd? czy jest z tym problem GitHub?
Alex
to da ci pomysł scommerce-mage.com/blog/…
stevensagaar

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.

Craig
źródło
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.

Edmund
źródło
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

Sameer Bhayani
źródło
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;
}
MageLearner
źródło
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
Praveen P. Rokade
źródło
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

Tahir Iqbal Najam
źródło
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 .

Głaskanie pod brodę
źródło
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;
}
Adam Jackson
źródło
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;
} 
mnojind
źródło
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!

Chris Rogers
źródło
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ął.

Binod
źródło
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.

Kirby
źródło
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
Alex
źródło
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';
gh darvishani
źródło
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.

Andy
źródło