0. 서문
PHP에서 직렬화의 결과는 json과 다소 유사한 PHP 사용자 정의 문자열 형식입니다.
us 직렬화 설계 어떤 언어로든 객체를 역직렬화하려면 여러 가지 문제를 해결해야 합니다. 객체를 직렬화한 후 직렬화 결과에는 자체 설명 기능이 있습니다(직렬화 결과에서 객체의 특정 세부 사항을 알 수 있음).
알고 있는 것만으로는 충분하지 않습니다. 물론 이 유형에 해당하는 특정 값도 알아야 합니다.)
직렬화 중 권한 제어, 직렬화 필드 등을 사용자 정의할 수 있습니다. 예를 들어 golang에서 수행하는 것이 매우 편리합니다.
시간 성능 문제: 고성능 서비스(직렬화를 위해 protobuf를 자주 사용함)와 같이 성능에 민감한 일부 시나리오에서는 객체 직렬화를 억제할 수 없습니다.
공간 성능 문제: 직렬화 후 결과가 너무 좋을 수 없습니다. 예를 들어, int 객체가 메모리에 있고 직렬화 후 데이터 길이가 int 길이의 10배가 되면 직렬화 알고리즘에 문제가 있는 것입니다.
이 문서에서는 관점에서 PHP의 시퀀스만 설명합니다. 직렬화 및 역직렬화 과정은 객체 데이터에서만 작동한다는 점을 기억하세요. 객체 지향 개발 경험이 있는 사람이라면 누구나 쉽게 이해할 수 있습니다.
PHP 프로그래밍 초보부터 마스터까지1. 직렬화 및 역직렬화 메서드 unserialize
php는 C++와 달리 객체 직렬화 기능을 기본적으로 제공합니다...^_^ 인터페이스도 두 개뿐이어서 사용하기도 매우 간단합니다.
class fobnn { public $hack_id; private $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { echo $this->hack_name.PHP_EOL; } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); //通过serialize接口序列化 echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr);//通过unserialize反序列化 $toobj->print();
fobnn O:5:"fobnn":2:{s:7:"hack_id";i:1;s:16:"fobnnhack_name";s:5:"fobnn";} fobnn
두 번째 줄을 참조하세요. 이 문자열은 실제로 읽기 쉽습니다. 물론 개체 유형 이후의 레이블 이름은 개체 이름/멤버 이름을 통해 매핑됩니다. 형식 이름은 fobnn입니다. 이 형식에서 다음 2는 멤버 개체가 두 개 있음을 나타냅니다.
멤버 개체에 대해서는 실제로 동일한 하위 설명 집합입니다.
자기- 함수 설명 주로 문자열을 통해 객체와 멤버의 이름을 기록하는 방식으로 구현됩니다.
2. 성능 문제
이 기사에서는 PHP 직렬화의 시간 성능을 분석하지 않지만 실제로 직렬화 결과는 다음과 같습니다. json/bson에서 정의한 프로토콜과 유사하게 프로토콜 헤더가 있고, 프로토콜 헤더는 유형을 설명하고, 프로토콜 본문은 유형에 해당하는 값을 설명하며, 직렬화 결과는 압축되지 않습니다. deserialization의 매직 메소드
에 해당합니다. 두 번째 문제는 실제로 PHP에 해결책이 있습니다. 하나는 매직 메소드를 통한 것이고, 두 번째는 사용자 정의 직렬화 함수를 통한 것입니다. 먼저 매직 메소드인 __sleep 및 __wakeup
을 소개하겠습니다.class fobnn { public $hack_id; private $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { echo $this->hack_name.PHP_EOL; } public function __sleep() { return array("hack_name"); } public function __wakeup() { $this->hack_name = 'haha'; } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr); $toobj->print();
fobnn O:5:"fobnn":1:{s:16:"fobnnhack_name";s:5:"fobnn";} haha
직렬화 전 __sleep이 먼저 호출되어 직렬화되어야 하는 멤버 이름 배열을 반환합니다. 이러한 방식으로 직렬화해야 하는 데이터를 제어할 수 있습니다. 이 경우에는 hack_name만 반환했습니다. code>. hack_name 멤버만 직렬화된 것을 볼 수 있습니다.
직렬화가 완료된 후 __wakeup
가 사용됩니다. 여기서는 데이터베이스에 다시 연결하는 등의 후속 작업을 수행할 수 있습니다.
3. 직렬화 가능 인터페이스 사용자 정의
interface Serializable { abstract public string serialize ( void ) abstract public void unserialize ( string $serialized ) }이 인터페이스를 통해 직렬화 및 역직렬화 동작을 사용자 정의할 수 있습니다.
class fobnn implements Serializable { public $hack_id; private $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { echo $this->hack_name.PHP_EOL; } public function __sleep() { return array('hack_name'); } public function __wakeup() { $this->hack_name = 'haha'; } public function serialize() { return json_encode(array('id' => $this->hack_id ,'name'=>$this->hack_name )); } public function unserialize($var) { $array = json_decode($var,true); $this->hack_name = $array['name']; $this->hack_id = $array['id']; } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr); $toobj->print();
fobnn C:5:"fobnn":23:{{"id":1,"name":"fobnn"}} fobnn사용자 정의 직렬화 인터페이스를 사용한 후에는 메소드는 쓸모가 없습니다.
hack_name
,可以看到结果中只序列化了hack_name成员.
在序列化完成之后,会跳用__wakeup
在这里我们可以做一些后续工作,例如重连数据库之类的.
3.自定义Serializable接口
class fobnn { public $hack_id; public $hack_name; public function __construct($name,$id) { $this->hack_name = $name; $this->hack_id = $id; } public function print() { var_dump($this->hack_name); } } $obj = new fobnn('fobnn',1); $obj->print(); $serializedstr = serialize($obj); echo $serializedstr.PHP_EOL;; $toobj = unserialize($serializedstr); $toobj->print(); $toobj2 = unserialize("O:5:\"fobnn\":2:{s:7:\"hack_id\";i:1;s:9:\"hack_name\";i:12345;}"); $toobj2->print();
通过这个接口我们可以自定义序列化和反序列化的行为,这个功能主要可以用来自定义我们的序列化格式.
string(5) "fobnn" O:5:"fobnn":2:{s:7:"hack_id";i:1;s:9:"hack_name";s:5:"fobnn";} string(5) "fobnn" int(12345)rrreee
当使用了自定义序列化接口之后,我们的魔术方法就没用了.
4.PHP动态类型和PHP反序列化
既然上文中提到的自描述功能,那么序列化结果中保存了对象的类型,且php是动态类型语言,那么我们就可以来做个简单的实验.
rrreee我们修改hack_name
反序列化的结果为int类型, i:12345
hack_name
의 역직렬화 결과를 int 유형으로 수정하면 i:12345
🎜rrreee🎜를 찾을 수 있습니다. 물론 이 PHP 메커니즘은 유연한 구문을 제공하지만 보안 위험도 발생합니다. 우리는 PHP 직렬화 및 역직렬화 기능으로 인해 발생하는 보안 문제를 계속 분석할 것입니다.위 내용은 PHP 직렬화 및 역직렬화 원리 직접 살펴보기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!