Magento 2.2: ไม่สามารถยกเลิกการตั้งค่าได้หรือไม่


33

พบปัญหาในเว็บไซต์ที่ใช้Magento 2.2.0-rc3.0 / PHP 7.0.23

ปัญหาต่อไปนี้เกิดขึ้นกับส่วนขยายของบุคคลที่สามทั้งหมดที่เปิดใช้งานหรือปิดใช้งาน

เมื่อเพิ่มรายการเพื่อเปรียบเทียบจากหมวดหมู่หรือหน้าผลิตภัณฑ์หรือส่งคำวิจารณ์จากหน้าผลิตภัณฑ์เราได้รับข้อผิดพลาดต่อไปนี้ในเบราว์เซอร์:

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}

ข้อผิดพลาดจะไม่หายไปเว้นแต่ว่าคุณจะล้างคุกกี้โดยเฉพาะคุกกี้ข้อความผู้วิเศษ ป้อนคำอธิบายรูปภาพที่นี่

ขอความช่วยเหลือในการแก้ไขปัญหาข้อผิดพลาดเหล่านี้


นั่นไม่ใช่ข้อบกพร่องหลักหรือ มีปัญหา GitHub สำหรับสิ่งนี้หรือไม่?
อเล็กซ์

สิ่งนี้จะทำให้คุณมีความคิดscommerce-mage.com/blog/…
stevensagaar

คำตอบ:


59

ฉันสามารถแก้ไขปัญหานี้ได้โดยการล้าง Redis Cache จาก CLI

redis-cli flushall

ฉันหวังว่านี่จะช่วยผู้ใช้ในอนาคต


2
ทำได้ดีมาก นี่อาจเป็นคำตอบที่ยอมรับได้
Shawn Abramson

ดูเหมือนจะไม่ได้เป็นทางออกเสมอไป ในกรณีของฉันฉันไม่ได้ใช้ redis (ยัง)
Alex

ขอบคุณ ฉันรีสตาร์ทวานิชโดยคิดว่าจะล้างออก แต่นี่เป็นกลอุบาย
ladle3000

มันใช้งานได้สำหรับฉัน
Jared Chu

สิ่งนี้ช่วยฉันในขณะอัปเกรดจาก 2.2.9 เป็น 2.3.2 ฉันพบข้อผิดพลาดเมื่อฉันเรียกใช้งานการตั้งค่า bin / magento
Mohammed Joraid

30

ปัญหาอยู่ใน /vendor/magento/framework/Serialize/Serializer/Json.php มีฟังก์ชัน unserialize ($ string) ซึ่งให้ข้อผิดพลาดทางไวยากรณ์กับคุณหากสตริงนั้นต่อเนื่องกัน (ไม่ใช่ json แต่เป็นอนุกรม php)

มีวิธีแก้ปัญหาคือ - คุณสามารถตรวจสอบว่าสตริงเป็นอนุกรม (vs json-encoded) แล้วใช้เป็นอันดับ ($ string) เปลี่ยน unserialize เป็น:

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

หลังจากบันทึก fe หมวดหมู่โดยไม่มีปัญหาคุณสามารถคืนค่าคลาสเป็นค่าเริ่มต้นและจะไม่มีปัญหาดังกล่าวในอนาคต


1
มันใช้งานได้ดี 100% สำหรับฉัน ขอบคุณมาก!
mapaladiya

2
มันไม่ทำงาน ... :-(
Arfan Mirza

ตรวจสอบสิ่งที่เกิดขึ้นหากส่งค่า a: 0: {} ไปทีละบรรทัด จะเกิดอะไรขึ้นถ้าผลลัพธ์ของ unserialize ถูกส่งผ่านไปยังวิธีการพิมพ์ที่คาดเดายาก คุณอาจต้องการเปลี่ยนคำตอบ
vitoriodachef

20

ห้ามแก้ไขไฟล์หลักเพื่อหาทางแก้ไข แทนที่ด้วยวิธีต่อไปนี้เพียงแค่ใส่บรรทัดต่อไปนี้ใน di.xml ภายในไดเรกทอรีอื่น ๆ

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

และภายในไดเรกทอรี Namespace \ ModuleName \ Serialize \ Serializer: ไฟล์ 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;
    }
}

ทำงานได้อย่างสมบูรณ์แบบ


2
การใช้งานมีข้อบกพร่อง จะเกิดอะไรขึ้นถ้าค่า a: 0: {} ถูกส่งผ่านไปยังวิธี Json: unserialize? มันเป็นพฤติกรรมที่ต้องการหรือไม่ จุดของตัวแปรผลลัพธ์ในเมธอด is_serialized คืออะไร มันจะไม่ถูกส่งกลับและมันจะไม่ส่งผลกระทบใด ๆ กับการเรียกเมธอดที่ไม่มีการส่งตัวแปรเป็นอาร์กิวเมนต์ที่สอง
vitoriodachef

นี่ควรเป็นโซลูชันที่ได้รับการยอมรับและดีกว่าการโพสต์ด้านบนเพื่อแก้ไขไฟล์โดยตรงในผู้ขาย คุณจะต้องเรียกใช้งานการอัปเกรดการตั้งค่าแบบโลคัลและจากนั้นอีกครั้งในการจัดเตรียม / การผลิตดังนั้นมันจะต้องคงสภาพแวดล้อมและผู้ขาย / ไดเรกทอรีเป็นสิ่งประดิษฐ์ที่สร้างขึ้นในเวลาสร้าง
Mark Shust

@ vitoriodachef ฉันกำลังเผชิญกับกรณีที่คุณพูดถึง คุณพบวิธีการแก้ปัญหาใด ๆ ?
Knight017

ฉันได้ใช้ฟังก์ชั่นต่อไปนี้เพื่อตัดสินใจว่าฟังก์ชั่นส่วนตัว isSerialized ($ value) {return (boolean) preg_match ('/ ^ ((s | i | d | b | a | O | C): | N;) /', $ value ); }
Knight017

ไม่ทำงาน ฉันต้องเปลี่ยนรายการทั้งหมดในฐานข้อมูลด้วยตนเองa:0:{}เป็น[]
localhost

16

ในกรณีของฉันฉันแก้ไขดังต่อไปนี้เพื่อยกเลิกการตั้งค่าสตริงที่ทำให้เป็นลำดับ: ไฟล์: /vendor/magento/framework/Serialize/Serializer/Json.php

หา:

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

แทนที่โดย:

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

ปัญหาได้รับการแก้ไขแล้ว ขอบคุณที่ถาม!
ศิวะ

1
ขอบคุณ ... ขอบคุณ !!!
MageLearner

1
ขอบคุณ @MageLearner มันทำงานใน 2.3.1 หลังจากย้ายข้อมูลจาก magento 1 ไปเป็น magento 2
Pradeep Thakur

5

หลังจากล้าง Redis ปัญหาได้เรียงลำดับ ขอบคุณCraigสำหรับการแก้ปัญหา

ฉันใช้พอร์ต 6379 สำหรับแคชดังนั้นฉันจึงเรียกใช้คำสั่ง:

redis-cli -p 6379 flushall

4

ส่วนใหญ่เกี่ยวข้องกับแคช Redis ดังนั้นพยายามล้างข้อมูลนี้ด้วยคำสั่งง่ายๆใน SSH ของคุณ

redis-cli flushall


3

มันกลายเป็นปัญหาการอนุญาตโดยที่วีโอไอพีตั้งค่าการอนุญาตสำหรับไฟล์ที่สร้างขึ้นซึ่งถูก จำกัด บนเซิร์ฟเวอร์นี้

แก้ไขโดยสร้างไฟล์ magento_umask ในไดเรกทอรีรากด้วย umask ที่เหมาะสมสำหรับเซิร์ฟเวอร์

ดูhttp://devdocs.magento.com/guides/v2.2/install-gde/install/post-install-umask.htmlสำหรับรายละเอียดเพิ่มเติม


สวัสดีฉันกำลังเผชิญหน้ากับปัญหาที่เกี่ยวข้องเช่นนี้ คุณสามารถโปรดดูในนี้
Aditya Shah

@ chunk ทั้งหมด dir ของฉันคือ 755 และไฟล์เป็น 644 umask ที่เหมาะสมในการตั้งค่าคืออะไร? tia
Kris Wen

2

คำตอบของ Sameers ได้ผลสำหรับฉันแม้ว่าฉันจะต้องใช้รหัสที่แตกต่างกันในบล็อก

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

ไดเรกทอรีราก 1 public_html/vendor/magento/framework/Serialize/Serializer/Json.php

ดาวน์โหลด JSON.php https://gist.github.com/manojind/9f18bbecaeb3e2bbfb056a634ade62a2

2. เพียงแค่แทนที่ฟังก์ชั่นด้านล่าง (ยกเลิกการตั้งค่า) และเพิ่มฟังก์ชั่นใหม่หรือเพียงแค่ดาวน์โหลดไฟล์ที่แนบมาและแทนที่ด้วยค่าเริ่มต้น

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. เพิ่มฟังก์ชั่นใหม่:

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

ปัญหาของฉันไม่ได้รับการแก้ไข .. โปรดช่วยฉันด้วย
Muhammad Ahmed

1

ฉันเองพบปัญหานี้เลี้ยงมันเป็นหัวหน้าใช้คำสั่ง:

php bin/magento setup:upgrade

หลังจากการย้ายถิ่น ฉันพบว่าฉันไม่มีแฮชคีย์" crypt " ในsrc/app/etc/env.php:

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

    ...

ตรวจสอบให้แน่ใจว่าสิ่งนี้ไม่ว่างเปล่าและเหมาะสมกับสภาพแวดล้อมอื่น ๆ ของโครงการของคุณ!


ฉันปล่อยคีย์ crypt ว่างไว้ในระหว่างการติดตั้งโดยคาดหวังว่าจะสร้างใหม่ซึ่งจะไม่เกิดขึ้นอย่างชัดเจน
Shapeshifter

0

ฉันได้รับข้อผิดพลาดในหน้า CMS ที่ส่วนหน้า

มันเป็นรหัสวิดเจ็ต Magento ในเนื้อหาหน้า CMS ที่ก่อให้เกิดปัญหา (ซึ่งฉันคัดลอกมาจากแหล่งอื่น) ฉันลบรหัสวิดเจ็ตและแทรกวิดเจ็ตเดียวกันโดยใช้ปุ่มแทรก Widget ในหน้าจอแก้ไขหน้า CMS และทำงานได้

กระบวนการข้างต้นจัดรูปแบบรหัสวิดเจ็ตแตกต่างกันและทำให้ข้อผิดพลาดหายไป


0

ฉันพบว่าข้อมูลที่เป็นอนุกรมทั้งหมดไม่สามารถใส่ลงในคอลัมน์ฐานข้อมูล MySQL ที่มีTEXTชนิดข้อมูลได้
ฉันเพิ่งพบว่าflag_dataค่าคอลัมน์ของsystem_config_snapshotบรรทัดถูกตัดออก

ฉันต้องเปลี่ยนเป็นMEDIUMTEXTคอลัมน์flag.flag_dataนี้


0

เป็นข้อผิดพลาดเดียวกัน เมื่อพยายามอัพเดทฐานข้อมูล (เวอร์ชั่น 2.2.6) ด้วยรหัสสด (เวอร์ชั่น 2.3.2)

สำหรับการแก้ไข - runned

composer update

0

นี่ไม่ใช่วิธีที่ดีที่สุดในการรัน sql โดยตรง แต่ฉันทำเพื่อประหยัดเวลา เพียงเรียกใช้แบบสอบถามนี้

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

หากคุณใช้ 2.3.0 หรือสูงกว่าคุณจะต้องใช้โซลูชันที่ MageLearner จัดหาให้ วิธีที่เก่ากว่าด้วยคำสั่ง case จะล้าสมัย หากคุณไม่ได้ใช้โซลูชันของ MageLearner ใน 2.3.0 หรือสูงกว่า; คุณจะพบกับปัญหาทุกประเภทเกี่ยวกับการดูข้อมูลการสั่งซื้อและผลิตภัณฑ์ที่กำหนดค่าได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.