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.