현재 위치: > 최신 기사 목록> PHP의 직렬화 기능을 사용할 때 데이터 손실을 피하는 방법은 무엇입니까?

PHP의 직렬화 기능을 사용할 때 데이터 손실을 피하는 방법은 무엇입니까?

gitbox 2025-05-19

PHP에서 Serialize 함수는 객체 또는 배열을 문자열로 변환하여 데이터베이스에 저장하거나 네트워크를 통해 전송할 수 있도록 사용됩니다. 그러나 직렬화 함수는 일부 복잡한 데이터를 처리 할 때, 특히 객체에 리소스 유형 (예 : 파일 핸들, 데이터베이스 연결 등)이 포함 된 경우 데이터 손실을 유발할 수 있습니다. 따라서 직렬화 기능을 올바르게 사용하는 방법을 이해하고 데이터 손실을 피하는 것이 매우 중요합니다.

1. 직렬화비 시련을 이해하십시오

직렬화 함수는 PHP 변수 (배열, 객체 등)를 저장 또는 전송할 수있는 문자열로 변환합니다. 비 제외 기능을 사용 하여이 문자열을 원래 PHP 데이터 유형으로 복원하십시오.

 $data = ['name' => 'John', 'age' => 30];
$serializedData = serialize($data);
echo $serializedData; // 문자열 양식의 출력 데이터

$unserializedData = unserialize($serializedData);
print_r($unserializedData); // 출력 배열 데이터

2. 데이터 손실을 일으킬 수있는 원인

Serialize를 사용하는 경우 데이터 손실을 유발하는 다음 상황이 발생할 수 있습니다.

(1) 객체에는 비 시리얼 리소스 유형이 포함되어 있습니다

PHP 객체의 리소스 유형 (예 : 데이터베이스 연결, 파일 핸들 등)은 직렬화 할 수 없습니다. 직렬화 된 문자열은 이러한 리소스를 잃게됩니다.

 $connection = mysqli_connect('localhost', 'user', 'password');
$serializedConnection = serialize($connection);
echo $serializedConnection; // 비어 있거나 불완전한 직렬화 된 문자열을 출력하십시오

(2) 비 제외 화를 사용하면 클래스가로드되지 않습니다.

직렬화 된 객체가 사용자 정의 클래스에 속하고 클래스가 비 서식 할 때 정의되지 않거나로드되지 않으면 비소화는 False를 반환하여 데이터 손실을 초래합니다.

 class Person {
    public $name;
}

$person = new Person();
$person->name = 'John';

$serializedPerson = serialize($person);

// 로드되지 않았다고 가정하십시오 Person 친절한
$unserializedPerson = unserialize($serializedPerson); // 반품 false

3. 데이터 손실을 피하는 방법?

(1) 직렬화 된 객체에 리소스 유형이 없는지 확인

직렬화 전에 객체에 파일 핸들, 데이터베이스 연결 등과 같은 리소스 유형이 포함되어 있지 않은지 확인하십시오. 이러한 리소스는 직렬화 전에 널로 제거하거나 저장할 수 있습니다.

 class MyClass {
    private $resource;

    public function __construct($resource) {
        $this->resource = $resource;
    }

    public function __sleep() {
        // 在序列化之前移除资源친절한型
        $this->resource = null;
        return ['resource']; // 반품需要序列化的属性
    }
}

$obj = new MyClass(mysqli_connect('localhost', 'user', 'password'));
$serializedObj = serialize($obj);

(2) __sleep__wakeup 마법 방법을 사용하십시오

복잡한 데이터를 포함하는 클래스의 경우 __sleep__wakeup 마법 방법을 구현하여 객체의 직렬화 프로세스를 제어 할 수 있습니다.

  • __sleep는 직렬화 전에 객체 데이터를 준비하는 데 사용됩니다.

  • __wakeup은 사막화 후 물체의 상태를 복원하는 데 사용됩니다.

 class MyClass {
    private $resource;

    public function __sleep() {
        // 清理或转换不可序列化的资源친절한型
        $this->resource = null;
        return ['resource']; // 필요한 데이터 만 직렬화하십시오
    }

    public function __wakeup() {
        // 자원 또는 기타 필요한 작업을 복구합니다
        $this->resource = mysqli_connect('localhost', 'user', 'password');
    }
}

$obj = new MyClass(mysqli_connect('localhost', 'user', 'password'));
$serializedObj = serialize($obj);
$unserializedObj = unserialize($serializedObj);

(3) 클래스가로드되었는지 확인하십시오

비 속기를 사용하는 경우 관련 클래스가 올바르게로드되었는지 확인하십시오. 자동로드 함수는 SPL_Autoload_register 를 통해 등록하여 필요할 때 클래스를 자동으로로드 할 수 있는지 확인할 수 있습니다.

 spl_autoload_register(function ($class) {
    include $class . '.php'; // 根据实际路径加载친절한文件
});

$serializedObj = '...'; // 직렬화 된 문자열
$obj = unserialize($serializedObj);

(4) JSON 직렬화 사용을 고려하십시오

경우에 따라 JSON은 자원 유형과 같은 문제를 피하기 때문에 JSON이 가장 일반적인 데이터 유형을 잘 처리하므로 데이터 직렬화의 대안으로 JSON을 사용하는 것이 더 신뢰할 수 있습니다.

 $data = ['name' => 'John', 'age' => 30];
$jsonData = json_encode($data);
echo $jsonData; // 산출 JSON 형식 데이터

$decodedData = json_decode($jsonData, true);
print_r($decodedData); // 산출原始数据

(5) URL 도메인 이름을 교체하십시오

직렬화 된 데이터를 처리 할 때 URL에 예측할 수없는 도메인 이름이 포함될 수 있습니다. 이러한 URL의 불일치 또는 오류를 피하려면 문자열 교체로 도메인 이름을 선택한 도메인 이름으로 통합 할 수 있습니다.

 $serializedData = 'http://example.com/path/to/resource';
$updatedData = str_replace('example.com', 'gitbox.net', $serializedData);
echo $updatedData; // 산출更新后的 URL