Magento 2.2: Tidak dapat meng-unserialize nilai?

33

Mengalami masalah di situs yang menjalankan Magento 2.2.0-rc3.0 / PHP 7.0.23

Masalah berikut ini terjadi dengan semua ekstensi pihak ke-3 diaktifkan atau dinonaktifkan.

Saat menambahkan item ke perbandingan dari kategori atau halaman produk atau mengirimkan ulasan dari halaman produk kami mendapatkan kesalahan berikut di browser:

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}

Kesalahan tidak hilang kecuali Anda menghapus cookie, khususnya, cookie pesan-mage. masukkan deskripsi gambar di sini

Setiap bantuan dalam mengatasi kesalahan ini sangat kami hargai.

Membuang
sumber
Bukankah itu bug inti? apakah ada masalah GitHub untuk ini?
Alex
ini akan memberi Anda ide scommerce-mage.com/blog/…
stevensagaar

Jawaban:

59

Saya bisa mengatasi masalah ini dengan Flushing Redis Cache saya dari CLI

redis-cli flushall

Saya harap ini membantu pengguna di masa depan.

Craig
sumber
2
Bagus sekali. Ini mungkin jawaban yang diterima.
Shawn Abramson
Tampaknya tidak selalu menjadi solusi. Dalam kasus saya saya bahkan tidak menggunakan Redis (belum)
Alex
Terima kasih. Saya memulai kembali pernis, berpikir itu akan menyiramnya, tetapi ini berhasil.
Ladle3000
itu bekerja untuk saya
Jared Chu
Ini membantu saya saat meningkatkan dari 2.2.9 ke 2.3.2. Saya mendapatkan kesalahan ketika saya menjalankan setup
Mohammed Joraid
30

Masalahnya ada di /vendor/magento/framework/Serialize/Serializer/Json.php ada fungsi unserialize ($ string) yang memberi Anda kesalahan sintaks jika string serial (bukan json tapi serialisasi php).

Ada solusi - Anda dapat memeriksa apakah string serial (vs json-encoded) dan kemudian menggunakan serialize ($ string). Ubah unserialize ke:

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

dan tambahkan fungsi untuk memeriksa apakah string diserialisasi:

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

Setelah menyimpan fe. kategori tanpa masalah, Anda dapat mengembalikan kelas ke default dan tidak akan ada masalah seperti itu di masa depan.

Edmund
sumber
1
Ini bekerja 100% baik untuk saya. Terima kasih banyak!
mapaladiya
2
itu tidak berfungsi ... :-(
Arfan Mirza
Periksa apa yang terjadi jika nilai a: 0: {} dilewatkan. Pergi baris demi baris. Apa yang terjadi jika hasil unserialize diteruskan ke metode yang diketik kuat yang mengharapkan array? Anda mungkin ingin mengubah jawaban Anda.
vitoriodachef
20

Jangan mengedit file inti untuk solusi. Mengganti cara berikut. Cukup masukkan baris berikut di di.xml di dalam direktori dll

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

Dan di dalam Namespace \ ModuleName \ Serialize \ Serializer Directory: file 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;
    }
}

Bekerja dengan sempurna

Sameer Bhayani
sumber
2
Implementasinya cacat. Apa yang terjadi jika nilai a: 0: {} diteruskan ke Json: metode unserialize? Apakah itu perilaku yang diinginkan? Apa poin dari variabel hasil dalam metode is_serialized? Itu tidak dikembalikan dan tidak memiliki dampak terhadap apa pun karena pada pemanggilan metode tidak ada variabel yang dilewatkan sebagai argumen kedua.
vitoriodachef
Ini harus menjadi solusi yang diterima, dan jauh lebih baik daripada posting di atas untuk mengedit file langsung di vendor. Kemungkinan besar, Anda harus menjalankan tugas peningkatan pengaturan secara lokal dan kemudian lagi pada pementasan / produksi, sehingga harus bertahan lingkungan dan vendor / direktori adalah artefak yang dibuat pada waktu membangun.
Mark Shust
@vitoriodachef Saya menghadapi kasus persis yang telah Anda sebutkan. Apakah Anda menemukan solusi?
Knight017
Saya telah menggunakan fungsi berikut untuk memutuskan fungsi privat isSerialized ($ value) {return (boolean) preg_match ('/ ^ ((s | i | d | b | a | O | C): | N;) /', $ value ); }
Knight017
Tidak bekerja Saya harus mengubah semua entri dalam DB secara manual dari a:0:{}menjadi[]
localhost
16

Dalam kasus saya, saya menambal sebagai berikut untuk membatalkan serial string: File: / vendor/magento/framework/Serialize/Serializer/Json.php

Menemukan:

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

ganti dengan:

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
sumber
Saya sudah mencoba ini tetapi tidak berfungsi seperti yang diharapkan. Adakah yang mencoba ini dan jika berhasil, tolong bantu saya
Siva
Masalah apa yang Anda hadapi?
MageLearner
Masalahnya diperbaiki. Terima kasih untuk bertanya!
Siwa
1
Grt ... Terima kasih !!!
MageLearner
1
Terima kasih @MageLearner, Ini juga berfungsi di 2.3.1 setelah memigrasikan data dari magento 1 ke magento 2
Pradeep Thakur
5

Setelah memerah Redis masalah telah diurutkan. Terima kasih Craig untuk solusinya.

Saya menggunakan port 6379 untuk cache, jadi saya menjalankan perintah:

redis-cli -p 6379 flushall
Praveen P. Rokade
sumber
4

Ini sebagian besar terkait dengan cache Redis, jadi cobalah untuk menghapus ini dengan perintah sederhana di SSH Anda

redis-cli flushall

Tahir Iqbal Najam
sumber
3

Itu ternyata menjadi masalah izin, di mana magento sedang mengatur izin untuk file yang dihasilkan yang dibatasi pada server ini.

Dipecahkan dengan membuat file magento_umask di direktori root dengan umask yang sesuai untuk server.

Lihat http://devdocs.magento.com/guides/v2.2/install-gde/install/post-install-umask.html untuk detail tambahan.

Membuang
sumber
Halo, saya menghadapi masalah terkait seperti ini. Bisakah Anda melihat ini ?
Aditya Shah
@Chunk semua dir saya adalah 755, dan file 644, apa umask yang sesuai untuk ditetapkan? tia
Kris Wen
2

Jawaban pengirim di atas bekerja untuk saya walaupun saya harus menggunakan kode yang berbeda di blok.

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
sumber
1

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

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

2. Cukup ganti fungsi di bawah ini (batalkan register) dan tambahkan fungsi baru ATAU unduh saja file yang terlampir dan ganti dengan default

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. Tambahkan fungsi baru:

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
sumber
Masalah saya belum diperbaiki .. Tolong bantu saya
Muhammad Ahmed
1

Saya pribadi menemukan bahwa masalah ini muncul karena kepala menjalankan perintah:

php bin/magento setup:upgrade

Setelah migrasi. Saya menemukan bahwa saya kehilangan kunci hash " crypt " di src/app/etc/env.php:

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

    ...

Pastikan ini tidak kosong dan sebaiknya cocok dengan lingkungan proyek Anda yang lain!

Chris Rogers
sumber
Saya meninggalkan kunci crypt kosong selama instalasi mengharapkan yang baru akan dihasilkan, yang jelas tidak terjadi.
Shapeshifter
0

Saya mendapatkan kesalahan di halaman CMS di ujung depan.

Itu adalah kode widget Magento di Konten Halaman CMS yang menyebabkan masalah (yang saya salin dari sumber lain). Saya menghapus kode widget dan memasukkan widget yang sama menggunakan tombol Sisipkan Widget di layar edit Halaman CMS dan berhasil.

Proses di atas memformat kode widget secara berbeda dan membuat kesalahan hilang.

Binod
sumber
0

Saya menemukan bahwa seluruh data serial tidak dapat masuk ke dalam kolom tabel database MySQL dengan TEXTtipe data.
Saya baru saja menemukan nilai kolom flag_datadari system_config_snapshotgaris terpangkas.

Saya harus mengubahnya ke MEDIUMTEXTuntuk kolom ini flag.flag_data.

Kirby
sumber
0

Kesalahan yang sama. Ketika mencoba memperbarui basis data (ver 2.2.6) dengan kode baru (ver 2.3.2).

Untuk memperbaiki - menjalankan

composer update
Alex
sumber
0

Ini bukan cara terbaik untuk menjalankan sql secara langsung tetapi saya melakukan itu untuk menghemat waktu saya. Jalankan saja pertanyaan ini

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
sumber
0

Jika Anda menggunakan 2.3.0 atau lebih tinggi, Anda akan ingin menggunakan solusi yang disediakan oleh MageLearner. Cara lama dengan pernyataan kasus sudah usang. Jika Anda tidak menggunakan solusi MageLearner di 2.3.0 atau lebih tinggi; Anda akan menghadapi semua jenis masalah dengan melihat data pesanan dan produk yang dapat dikonfigurasi.

Andy
sumber