직렬화는 아마도 일부 변수를 문자열의 바이트 스트림으로 변환하는 것이므로 전송 및 저장이 더 쉬워집니다. 물론, 전송이나 저장과는 아무런 관련이 없습니다. 핵심은 다시 문자열 형식으로 변환할 수 있고 원래의 데이터 구조를 유지할 수 있다는 것입니다.
PHP에는 많은 직렬화 함수가 있습니다: serialize(). 이 함수는 모든 변수 값(리소스 변수 제외)을 문자열 형식으로 변환합니다. 문자열은 파일에 저장하거나 세션으로 등록할 수 있으며 심지어 컬을 사용하여 사용할 수도 있습니다. RPC 효과를 얻기 위해 GET/POST를 시뮬레이션하여 변수를 전송합니다.
직렬화된 변수를 PHP 원래 변수 값으로 변환하려면 unserialize() 함수를 사용할 수 있습니다.
1. 변수 직렬화
직렬화와 그 저장 형식을 설명하기 위해 간단한 예를 들어보겠습니다.
정수 유형:
$var = 23;
(
$var);
문자열:
$
var = 1.23;
echo
serialize
(
$var)
;
에코 직렬화($var);
$var = "나는 변수입니다";
echo serialize($var);
출력:
s:16:"이것은 문자열입니다.";
s:8: "나는 변수입니다.";
부울 유형:
$var = true;
에코 직렬화($var);
$var = 거짓;
echo 직렬화($var)
출력:
b:1;
b:0;
위의 기본 유형을 직렬화한 후의 상황은 매우 명확합니다.
변수 유형: [변수 길이:] 변수 값;
즉, 첫 번째 문자는 변수 유형을 나타냅니다. 분할을 나타냅니다. 즉, 문자열 유형에서는 사용할 수 있지만 다른 유형에서는 사용할 수 없습니다. 마지막 변수 값은 ";"으로 끝납니다.
예를 들어, 정수 23이 직렬화되면 i:23이 되며 길이는 없고 유형과 변수 값만 있고 i는 콜론으로 구분된 정수를 나타내고 부동 소수점을 포함하여 정수 값 23이 나중에 저장됩니다. 유형(더블)바이트 유형)과 동일합니다. Boolean의 경우 유형은 b(부울)입니다. true인 경우 직렬화된 값은 1입니다. false인 경우 값은 0입니다.
문자열
값의 경우 중간에 "This is a string"이라는 문자열과 같이 문자열의 길이 값을 저장하는 추가 저장 값이 있으며 생성된 직렬화된 값은 s:16:"This is a string입니다. "; s는 유형을 나타내는 문자열입니다. 가운데 16은 문자열의 길이입니다. 중국어라면 각 한자가 2자로 저장됩니다. 예를 들어 문자열 "나는 변수입니다", 생성된 직렬화 값은 :s:8:"I am a Variable"입니다. 길이는 8자입니다.
다음으로 배열 변수의 직렬화에 중점을 둡니다.
배열 변수:
$var = array("abc", "def", "xyz", "123");
echo 직렬화($var);
출력:
a:4:{i:0;s:3:"abc";i:1;s:3:"def";i:2;s:3:"xyz"; i:3;s:3:"123";}은
내 배열 $var를 직렬화하여 얻은 문자열 값입니다. $var 배열에는 "abc", "def" , "xyz", "123"이라는 4개의 문자열 요소가 포함되어 있습니다. , 직렬화된 데이터를 분석해 보겠습니다. 단순화를 위해 직렬화된 데이터를 배열 형식(
a:4)
으로 나열합니다.
{
i:0;s:3:"abc";
i:1;s:3:"def";
i:2;s:3:"xyz";
i:3;s:3:"123";
}
배열이 더 명확해졌습니다. 시작 문자열을 보면: a:4:{...} 먼저 첫 번째 문자 a는 변수 유형, 즉 배열(배열) 유형을 저장하고 두 번째 4는 배열 요소를 저장합니다. 의 개수는 총 4개이고 그 다음에는 {} 사이에 배열 요소의 내용이 있습니다. 예를 들어 첫 번째 배열 요소 i:0;s:3:"abc"; i는 현재 배열 요소의 인덱스 값 유형이 정수이고 값이 0이며 요소 값 유형이 s(문자열)임을 나타냅니다. ), 숫자는 3이고 특정 값은 "abc"이며 세미콜론으로 끝나는 식으로 다음 배열 요소에 대해 적용됩니다.
문자열을 요소 인덱스로 사용하면 어떤 일이 발생하는지 살펴보겠습니다.
$var = array("index1"=>"abc", "index2"=>"def", "index3"=>"xyz", "index4" = >"123");
echo 직렬화($var);
출력:
a:4:{s:6:"index1";s:3:"abc";s:6:"index2";s:3:"def";s:6: "index3";s:3:"xyz";s:6:"index4";s:3:"123";}
배열 스타일로 변경한 후:
a:4:
{
s:6:"색인1";s:3:"abc";
s:6:"index2";s:3:"def";
s:6:"index3";s:3:"xyz";
s:6:"색인4";s:3:"123";
}
실제로 시작 인덱스가 문자열을 저장하는 형태로 변경된다는 점을 제외하면 위와 크게 다르지 않습니다. 예를 들어 첫 번째 요소는 s:6: "index1"; 첫 번째 항목은 인덱스입니다. 값: s:6:"index1"은 유형이고, 6은 인덱스 문자열의 길이이며, "index1"은 인덱스 값입니다. 다음 s:3:"abc";는 요소 값입니다. 이는 이해하기 쉽기 때문에 자세히 설명하지 않겠습니다.
위에서 우리는 기본 데이터 유형의 직렬화에 대한 일반적인 이해를 얻었습니다. 실제로 자체 직렬화 기능을 구성하거나 이러한 관점에서 확장하여 자체 직렬화 프로그램을 개발하여 변수 교환을 용이하게 할 수 있습니다.
물론 실제로 이 함수를 사용하여 배열이나 다른 변수를 문자열로 직렬화한 다음 컬 함수를 사용하여 사용자가 작업을 수행하지 않고도 원격 서버에서 데이터를 가져오는 GET/POST 함수를 시뮬레이션할 수도 있습니다.
2. 객체 직렬화
객체 직렬화는 객체를 직렬화하여 저장하거나 전송할 수 있는 문자열로 변환할 수 있는 비교적 일반적인 기능입니다.
먼저 예제를 살펴보겠습니다:
class TestClass
{
var $a;
var $b;
함수 테스트클래스()
{
$this->a = "이것은 a입니다";
$this->b = "이것은 b입니다";
}
함수 getA()
{
$this->a를 반환합니다.
}
함수 getB()
{
$this->b를 반환합니다.
}
}
$obj = 새로운 TestClass;
$str = 직렬화($obj);
echo $str;
출력 결과:
O:9:"TestClass":2:{s:1:"a";s:9:"This is a";s:1:"b";s:9:"This is b";}
객체를 직렬화한 후 문자열을 분석해 보겠습니다.
O:9:"테스트클래스":2:
{
s:1:"a";s:9:"이것은 a입니다";
s:1:"b";s:9:"이것은 b입니다";
}
먼저 개체 자체의 콘텐츠를 살펴보세요. O:9:"TestClass":2:O는 이것이 개체 유형(개체)임을 나타내고, 9는 개체 이름을 나타내고, 2는 개체 수를 나타냅니다. 재산. 두 속성의 내용을 보면:
s:1:"a";s:9:"This is a"; 사실 첫 번째 항목인 s:1:"a의 내용과 유사합니다. ";는 설명 속성 이름입니다. , 두 번째 항목 s:9: "This is a";는 속성 값을 설명합니다. 다음 속성은 유사합니다.
먼저 객체 직렬화 적용에 대해 이야기하겠습니다. 다음 내용은 PHP 매뉴얼에서 가져온 것이며 원본 텍스트는 변경되지 않았습니다.
serialize()는 PHP에 저장할 수 있는 모든 값의 바이트 스트림 표현을 포함하는 문자열을 반환합니다. unserialize()는 이 문자열을 사용하여 원래 변수 값을 재구성할 수 있습니다. 직렬화를 사용하여 객체를 저장하면 객체의 모든 변수가 저장됩니다. 객체의 함수는 저장되지 않고 클래스 이름만 저장됩니다.
객체를 unserialize()하려면 객체의 클래스를 정의해야 합니다. 즉, page1.php에서 클래스 A의 객체 $a를 직렬화하면 클래스 A를 가리키며 $a의 모든 변수 값을 포함하는 문자열을 얻게 됩니다. page2.php에서 이를 역직렬화하고 클래스 A의 $a 객체를 재구성하려면 클래스 A의 정의가 page2.php에 나타나야 합니다. 예를 들어 클래스 A의 정의를 포함 파일에 배치하고 이 파일을 page1.php 및 page2.php에 포함하면 이를 달성할 수 있습니다.
<?php
// classa.inc:
클래스 A
{
var $one = 1;
함수 show_one()
{
echo $this->one;
}
}
// 페이지1.php:
include("classa.inc");
$a = 새로운 A;
$s = 직렬화($a);
// $s를 page2.php가 찾을 수 있도록 어딘가에 저장합니다.
$fp = fopen("저장소", "w");
fputs($fp, $s);
fclose($fp);
// 페이지2.php:
// 이 줄은 일반적인 역직렬화에 필요합니다.
include("classa.inc");
$s = implode("", @file("store"));
$a = unserialize($s);
// 이제 $a 객체의 show_one() 함수를 사용할 수 있습니다.
$a->show_one();
?>
세션을 사용하고 session_register()를 사용하여 객체를 등록하는 경우 이러한 객체는 각 PHP 페이지 끝에서 자동으로 직렬화되고 각 후속 페이지에서 자동으로 역직렬화됩니다. 기본적으로 이는 이러한 개체가 세션의 일부가 되면 모든 페이지에 나타날 수 있음을 의미합니다.
이러한 클래스가 모든 페이지에서 사용되지 않더라도 모든 페이지에 등록된 개체에 대한 클래스 정의를 포함하는 것이 좋습니다. 이것이 완료되지 않고 객체가 역직렬화되었지만 클래스가 정의되지 않은 경우 연관된 클래스를 잃고 사용 가능한 기능이 전혀 없는 stdClass의 객체가 됩니다. 이는 매우 쓸모가 없습니다.
따라서 위의 예에서 session_register("a")를 실행하여 $a가 세션의 일부가 되면 classa.inc 파일은 page1.php 및 page2.php뿐만 아니라 모든 페이지에 포함되어야 합니다.
물론 직렬화된 객체는 실제로 여러 곳에 적용될 수 있습니다. 물론, 직렬화는 PHP 5에서 다르게 처리됩니다. 설명서에 나와 있는 내용을 살펴보겠습니다.
serialize()는 클래스에 마법 이름 __sleep을 가진 함수가 있는지 확인합니다. 그렇다면 함수는 직렬화 전에 실행됩니다. 개체를 지우고 직렬화해야 하는 개체의 모든 변수 이름이 포함된 배열을 반환해야 합니다.
__sleep을 사용하는 목적은 개체에 있을 수 있는 모든 데이터베이스 연결을 닫거나, 보류 중인 데이터를 제출하거나, 유사한 정리 작업을 수행하는 것입니다. 또한 이 기능은 완전히 저장할 필요가 없는 매우 큰 개체가 있는 경우에도 유용합니다.
반대로, unserialize()는 매직 이름이 __wakeup인 함수가 있는지 확인합니다. 이 함수는 객체에 있을 수 있는 모든 리소스(있는 경우)를 재구성할 수 있습니다.
__wakeup을 사용하는 목적은 직렬화 중에 손실되었을 수 있는 데이터베이스 연결을 다시 설정하고 기타 재초기화 작업을 처리하는 것입니다.