마 젠토 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}

쿠키, 특히 mage-messages 쿠키를 지우지 않으면 오류가 사라지지 않습니다. 여기에 이미지 설명을 입력하십시오

이러한 오류 문제 해결에 도움이 필요합니다.


그게 핵심 버그 아닌가요? 이것에 대한 GitHub 문제가 있습니까?
Alex

이것은 당신에게 아이디어를 줄 것입니다 scommerce-mage.com/blog/…
stevensagaar

답변:


59

CLI에서 Redis 캐시를 플러시하여이 문제를 해결할 수있었습니다.

redis-cli flushall

이것이 향후 사용자에게 도움이되기를 바랍니다.


2
잘 했어요 이것은 아마도 대답이 될 것입니다.
Shawn Abramson

항상 해결책은 아닙니다. 내 경우에는 redis (아직)를 사용하지도 않습니다
Alex

감사. 나는 그것을 씻어 내릴 것이라고 생각하면서 니스를 다시 시작했지만, 이것은 속임수였습니다.
ladle3000

그것은 나를 위해 작동
Jared Chu

이것은 2.2.9에서 2.3.2로 업그레이드하는 동안 도움이되었습니다. PHP bin / magento setup을
Mohammed Joraid

30

문제는 /vendor/magento/framework/Serialize/Serializer/Json.php에 있으며 문자열이 직렬화 된 경우 구문 오류를 제공하는 unserialize ($ string) 함수가 있습니다 (json이 아니라 PHP 직렬화).

해결 방법이 있습니다-문자열이 직렬화되었는지 (vs-sonson-encoded) serialize ($ string)를 사용할 수 있는지 확인할 수 있습니다. 직렬화 해제를 다음으로 변경하십시오.

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 : {} 값이 전달되면 어떻게되는지 확인하십시오. 한 줄씩 가십시오. 직렬화 해제 결과가 배열을 예상하는 강력한 유형의 메소드로 전달되면 어떻게됩니까? 답을 바꾸고 싶을 수도 있습니다.
vitoriodachef 님

20

솔루션의 핵심 파일을 편집하지 마십시오. 다음과 같은 방법으로 재정의하십시오.

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

그리고 Namespace \ ModuleName \ Serialize \ Serializer 디렉토리 안에 : 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;
    }
}

완벽하게 작동


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

필자의 경우 직렬화 된 문자열을 직렬화 해제하기 위해 다음과 같이 패치했습니다. File : /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;
}

나는 이것을 시도했지만 예상대로 작동하지 않습니다. 누구든지 이것을 시도하고 그것이 효과가 있다면, 도와주세요
Siva

어떤 문제가 발생 했습니까?
MageLearner

문제가 해결되었습니다. 질문 주셔서 감사합니다!
Siva

1
Grt ... 감사합니다 !!!
MageLearner

1
감사합니다 @MageLearner, magento 1에서 magento 2로 데이터를 마이그레이션 한 후 2.3.1에서도 작동합니다.
Pradeep Thakur

5

Redis를 플러시 한 후 문제가 정렬되었습니다. 솔루션에 대해 Craig 에게 감사합니다 .

캐시에 포트 6379를 사용하고 있으므로 명령을 실행하십시오.

redis-cli -p 6379 flushall

4

주로 Redis 캐시와 관련이 있으므로 SSH에서 간단한 명령으로 플러시하십시오.

레디 스 클리 플러시 올


3

magento가이 서버에서 제한된 생성 된 파일에 대한 권한을 설정하는 권한 문제로 판명되었습니다.

서버에 적합한 umask를 사용하여 루트 디렉토리에 magento_umask 파일을 작성하여 해결합니다.

자세한 내용은 http://devdocs.magento.com/guides/v2.2/install-gde/install/post-install-umask.html 을 참조 하십시오 .


안녕하세요, 나는 이와 같은 관련 문제에 직면하고 있습니다. 이것 좀 봐주세요 .
Aditya Shah

@ chunk 내 모든 디렉토리는 755이고 파일은 644입니다. 설정할 적절한 umask는 무엇입니까? tia
크리스 원

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

루트 디렉토리 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'
    ],

    ...

비어 있지 않아야하며 프로젝트의 다른 환경과 일치해야합니다!


새 키가 생성 될 것으로 예상되는 설치 중에 암호화 키를 비워 두었습니다.
Shapeshifter

0

프런트 엔드의 CMS 페이지에서 오류가 발생했습니다.

CMS 페이지 콘텐츠에서 Magento 위젯 코드로 문제를 일으켰습니다 (다른 소스에서 복사). CMS 코드 편집 화면의 위젯 삽입 버튼을 사용하여 위젯 코드를 삭제하고 동일한 위젯을 삽입했습니다.

위의 프로세스는 위젯 코드의 형식을 다르게하여 오류를 해결했습니다.


0

전체 직렬화 된 데이터를 TEXT데이터 유형이 있는 데이터베이스 MySQL 테이블 열에 맞출 수 없다는 것을 알았습니다 .
방금 줄 의 열 flag_data값이 잘 system_config_snapshot립니다.

나는 MEDIUMTEXT이 칼럼 을 위해 그것을 바꿔야했다 flag.flag_data.


0

같은 오류였습니다. 새로운 코드 (ver 2.3.2)로 데이터베이스 (ver 2.2.6)를 업데이트하려고 할 때.

수정-실행

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 문을 사용하는 오래된 방법은 더 이상 사용되지 않습니다. 2.3.0 이상에서 MageLearner의 솔루션을 사용하지 않는 경우 주문 데이터 및 구성 가능한 제품을 볼 때 모든 종류의 문제가 발생합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.