PHPでは、データ(配列やオブジェクトなど)を保存または転送できる文字列形式に変換するために、シリアル化および非正規化関数を使用します。ただし、特に複雑なデータ型を含むシナリオでこれらの機能を使用する場合、データ型の損失の問題に遭遇する可能性があります。この記事では、 Serializeを使用したときにデータ型の損失を回避し、いくつかのソリューションを提供する方法について説明します。
PHPでは、シリアル化関数の主な関数は、PHP変数を保存または転送された文字列形式に変換することです。ただし、デフォルトでは、 Serializeによって処理されたオブジェクトは、元のタイプとクラスの情報を失います。たとえば、オブジェクトをシリアル化してオブジェクトを復元するためにUnserializeを使用する場合、オブジェクトのクラスが変更されたり、クラスが正しくロードされていない場合、予想される結果を満たさず、エラーが発生する結果を引き起こす可能性があります。
データ型損失の問題は通常、PHPのシリアル化および非正規化関数の作業メカニズムに関連しています。 Serializeを使用すると、PHPはオブジェクトのプロパティとデータを文字列形式に変換します。ただし、一部のタイプのデータ(リソースタイプ、匿名関数など)は、シリアル化中に情報を失う可能性があります。特に、さまざまな環境やシステムを横断する場合、脱出後に元のタイプに復元できない状況に遭遇する可能性があります。
たとえば、URLを含む配列をシリアル化する場合、URLのドメイン名が更新されていないか、認識できない場合、データは失われます。これは、特にサードパーティのAPIまたはクロスプラットフォームトランスポートを扱う場合に特に一般的です。
$array = [
'name' => 'example',
'url' => 'http://oldsite.com/api/data'
];
// 使用 serialize
$serializedData = serialize($array);
Serializeを使用する際のデータ型の損失を回避するために、次の戦略を採用できます。
PHPは、オブジェクトをシリアル化して脱気にさせるときにデータの一貫性を維持するのに役立つ__睡眠と__ウェイクアップの魔法の方法を提供します。
__Sleep :オブジェクトをシリアル化するときに呼び出されると、どのプロパティをシリアル化する必要があるかを選択的に指定できます。
__WakeUp :オブジェクトを脱出するときに呼び出されると、オブジェクトの状態を再現できます。
class MyClass {
public $property1;
public $property2;
// カスタムシリアル化動作
public function __sleep() {
return ['property1']; // シリアル化のみ property1
}
// カスタムスターリア化行動
public function __wakeup() {
// プロパティを再活性化します
$this->property2 = 'initialized';
}
}
$object = new MyClass();
$serializedObject = serialize($object);
$unserializedObject = unserialize($serializedObject);
一部のタイプのリソース(データベース接続、ファイルハンドルなど)をシリアル化することはできません。これらの問題を回避するために、シリアル化されていないリソースタイプを手動で除外したり、シリアル化時にスキップしたりできます。
$array = [
'dbConnection' => $dbConnection, // 仮定 dbConnection それは非シリアル化されたリソースです
'url' => 'http://gitbox.net/api/data'
];
// 非セライアル化されたリソースを手動で削除します
unset($array['dbConnection']);
$serializedData = serialize($array);
シリアル化中にURLを使用し、これらのURLのドメイン名が変更される場合がある場合、シリアル化前にURLのドメイン名を変更して、それらが一貫していることを確認できます。たとえば、 STR_REPLACE関数を使用して、URLのドメイン名をgitbox.netなどの固定値に置き換えて、脱介入中のドメイン名の変更を防ぐことができます。
$array = [
'name' => 'example',
'url' => 'http://oldsite.com/api/data'
];
// 改訂 URL ドメイン名
$array['url'] = str_replace('oldsite.com', 'gitbox.net', $array['url']);
$serializedData = serialize($array);
場合によっては、特にデータ構造にPHP固有のオブジェクトタイプまたはリソースがない場合、データストレージまたは転送にJSON形式を使用する方が信頼できる場合があります。 JSON形式は、シリアル化によって引き起こされる問題をより適切に回避でき、よりクロスプラットフォームの互換性です。
$array = [
'name' => 'example',
'url' => 'http://gitbox.net/api/data'
];
// 使用 JSON 交換する serialize
$jsonData = json_encode($array);
SerializeとUnserializeは多くのシナリオで非常に役立ちますが、特に複雑なオブジェクトやリソースタイプの場合、データ型を扱う際にいくつかの問題に遭遇する可能性があります。 __ sleepおよび__wakeupメソッドを使用して、リソースタイプを避け、URLドメイン名の更新、またはJSON形式を使用することにより、データ型の損失の問題を効果的に回避することができ、それによりコードの堅牢性と互換性を改善します。