Serializable 인터페이스를 사용하여 PHP 클래스의 정렬화를 사용자 정의하는 방법

PHP의 객체 서열화에 관해서는 앞서 언급한 바 있습니다 __sleep () 및 __weakup () 이 두 가지 마술 방법.오늘 우리가 소개한 것은 또 다른 서열화된 내용을 제어할 수 있는 방식인데, 그것은 바로 Serializable 인터페이스를 사용하는 것이다.그것의 사용은 상술한 두 가지 마술 방법과 매우 유사하지만 약간 다르다.

Serializable 인터페이스


class A implements Serializable {
    private $data;
    public function __construct(){
        echo '__construct', PHP_EOL;
        $this->data = "This is Class A";
    }

    public function serialize(){
        echo 'serialize', PHP_EOL;
        return serialize($this->data);
    }

    public function unserialize($data){
        echo 'unserialize', PHP_EOL;
        $this->data = unserialize($data);
    }

    public function __destruct(){
        echo '__destruct', PHP_EOL;
    }

    public function __weakup(){
        echo '__weakup', PHP_EOL;
    }

    public function __sleep(){
        echo '__destruct', PHP_EOL;
    }
    
}

$a = new A();
$aSerialize = serialize($a);

var_dump($aSerialize);
// "C:1:"A":23:{s:15:"This is Class A";}"
$a1 = unserialize($aSerialize);
var_dump($a1);
이 코드는 Serializable 인터페이스를 사용하여 서열화 처리를 하는 것입니다. 주의하십시오. Serializable 인터페이스의 클래스 중__를 실현했습니다.sleep () 및 __weakup () 마술 방법은 무효입니다. 서열화할 때 들어가지 않습니다.
Serializable이라는 인터페이스가 실현해야 할 것은 두 가지 방법이다. serialize () 방법과 unserialize () 방법은 그 두 가지 마술 방법과 완전히 같지 않다.물론 사용하는 방식도 마찬가지다.
여기서 우리는 서열화된 지식을 좀 더 보급한다.대상의 서열화는 그들의 속성만 서열화할 수 있을 뿐, 그들의 방법을 서열화할 수 없다.현재 대응하는 클래스 템플릿을 찾을 수 있다면, 이 클래스를 복원하는 방법을 찾을 수 있고, 이 클래스를 정의한 템플릿이 없다면, 복원된 클래스는 속성만 있는 방법이 없습니다.우리는 이 코드의 서열화된 문자열을 통해 분석한다.
  • 'C:'는 현재 데이터의 유형을 가리킨다. 이 내 뒤에서 Serializable 인터페이스를 실현하는 대상의 서열화 결과는 C:이고 이 인터페이스를 실현하지 못한 대상의 서열화 결과는 O:라고 말할 수 있다
  • "A:", 분명히 대응하는 것은 클래스 이름, 즉 클래스::class
  • '{xxx}', 대상 구조는 JSON과 마찬가지로 괄호로도 사용된다
  • 각종 유형의 데이터가 서열화된 결과


    다음은 서로 다른 유형의 서열화 결과를 다시 봅시다.PHP에서 우리는 핸들 유형의 데이터를 제외하고 다른 표량 유형이나 수조, 대상은 모두 서열화할 수 있는데, 그것들은 서열화 문자열에서 어떻게 표현되는지 알아야 한다.
    
    $int = 110;
    $string = '110';
    $bool = FALSE;
    $null = NULL;
    $array = [1,2,3];
    
    var_dump(serialize($int)); // "i:110;"
    var_dump(serialize($string)); // "s:3:"110";"
    var_dump(serialize($bool)); // "b:0;"
    var_dump(serialize($null)); // "N;"
    var_dump(serialize($array)); // "a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}"
    
    위의 내용은 비교적 이해하기 쉽겠지.하지만 우리는 하나하나 설명해 봅시다.
  • 숫자 유형: i:<값>
  • 문자열 유형:<길이>:<값>
  • 부울 유형: b:<값: 0 또는 1>
  • NULL 유형: N;
  • 수조: a:<길이>:<내용>
  • 대상이 Serializable 인터페이스를 사용하여 서열화할 때 주의해야 할 점


    다음에 우리는 대상 유형을 중점적으로 이야기한다. 위에서 언급한 바와 같이 Serializable 인터페이스의 대상 서열화를 실현한 후의 표지는 특수한 상황이 있다.위의 서열화된 문자열의 시작 형식은 "C:"로 표시되어 있습니다. 그러면 Serializable 인터페이스를 실현하지 않는 대상의 서열화된 후에 어떤 상황인지 봅시다.
    
    //  
    class B {
        private $data = "This is Class B";
    
    }
    $b = new B();
    $bSerialize = serialize($b);
    
    var_dump ($bSerialize); // "O:1:"B":1:{s:7:"Bdata";s:15:"This is Class B";}"
    var_dump($bSerialize);
    var_dump(unserialize("O:1:\"B\":1:{s:7:\"\0B\0data\";s:15:\"This is Class B\";}"));
    
    // object(B)#4 (1) {
    //     ["data":"B":private]=>string(15) "This is Class B"
    // }
    
    역시, 그것의 시작 유형 표지는 "O:"이다.그러면 알 수 있듯이'C:'는 매우 큰 확률로 현재 서열화된 내용이 하나의 유형이고 하나의 대상 유형이 아니라는 것을 가리킨다.그들 사이에는 사실 현저한 차이가 없고, 공식 문서를 포함해서도 특별한 구체적인 설명을 찾지 못했다.만약 이 방면의 연구가 있거나 관련 자료가 있는 학생은 댓글로 함께 토론할 수 있다.
    그 밖에 만약에 우리가 수동으로 한 대상의 O:를 C:로 바꾸면 어떻게 될까요?
    
    //  O: C:
    var_dump(unserialize(str_replace('O:', 'C:', $bSerialize))); // false
    
    죄송합니다. 되돌릴 수 없습니다.그러면 우리는 반대로 위의 A클래스, 즉 Serializable 인터페이스의 서열화 문자열 중의 "C:"를 "O:"로 바꿉니까?
    
    // Warning: Erroneous data format for unserializing 'A'
    var_dump(unserialize(str_replace('C:', 'O:', $aSerialize))); // false
    
    응, 경고 하나를 알려주고 복원할 수도 없어.이렇게 보면 우리의 반서열화는 여전히 매우 지능적이어서 조금의 차이도 복원 조작을 할 수 없다.

    정의되지 않은 클래스의 반서열화 작업


    마지막으로 정의되지 않은 클래스의 경우 대상을 직접 반서열화합니다.
    
    //  D 
    var_dump(unserialize("O:1:\"D\":2:{s:7:\"\0D\0data\";s:15:\"This is Class D\";s:3:\"int\";i:220;}"));
    
    // object(__PHP_Incomplete_Class)#4 (3) {
    //     ["__PHP_Incomplete_Class_Name"]=>string(1) "D"
    //     ["data":"D":private]=>string(15) "This is Class D"
    //     ["int"]=>int(220)
    // }
    
    //  O: C:
    var_dump(unserialize(str_replace('O:', 'C:', "O:1:\"D\":2:{s:7:\"\0D\0data\";s:15:\"This is Class D\";s:3:\"int\";i:220;}"))); // false
    
    코드에서 알 수 있듯이 "C:"유형의 문자열은 여전히 반서열화에 성공할 수 없습니다.중점을 긋겠습니다. 만약에 C:처음에 서열화된 문자열이라면 반드시 정의되고 Serializable 인터페이스를 실현한 클래스가 있어야만 반서열화에 성공할 수 있습니다.
    또한 서열화된 문자열의 템플릿이 존재하지 않을 때 반서열화된 클래스의 클래스 이름은 __PHP_Incomplete_Class_Name 클래스, 클래스 템플릿의 반서열화 성공과는 달리 정상적인 클래스 이름입니다.

    총결산


    사실 상기 여러 가지를 보면 개인이 데이터를 저장하거나 전달하려면 서열화가 최선의 선택이 아니라고 느낀다.유형과 길이가 포함되어 있기 때문에 형식이 더욱 엄격해지고 반서열화된 내용이 대응하는 클래스 템플릿 정의가 없으면 특별히 사용하기 좋지 않기 때문에 차라리 JSON을 직접 사용해서 쉽게 읽는 것이 낫다.물론 구체적인 상황을 구체적으로 분석하면 우리는 장면을 결합시켜 적당한 사용 방식을 선택해야 한다.
    테스트 코드:
    github.com/zhangyue050…
    다음은 Serializable 인터페이스를 사용하여 PHP의 클래스를 정렬하는 방법에 대한 상세한 내용입니다. 사용자 정의 PHP의 클래스를 정렬하는 방법에 대한 더 많은 자료는 저희 다른 관련 글을 주목해 주십시오!

    좋은 웹페이지 즐겨찾기