【PHP8.x】Serializable::serialize()メソッドの使い方
serializeメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
serializeメソッドは、PHPのSerializableインターフェースを実装したクラスにおいて、オブジェクトを文字列形式に変換する(シリアライズする)直前に、PHPの実行環境によって自動的に呼び出されるメソッドです。このメソッドの主な目的は、オブジェクトの状態を適切に保存・復元するためのカスタムロジックを提供することにあります。
通常、PHPのserialize()関数を使ってオブジェクトを文字列化する際、そのプロパティは自動的に処理されます。しかし、データベース接続やファイルハンドルなどのリソース、あるいは動的に計算されるような特定のデータなど、標準のシリアライズでは適切に扱えないプロパティを持つオブジェクトも存在します。Serializableインターフェースを実装し、このserializeメソッドを定義することで、開発者はオブジェクトのどのデータをどのように文字列化するかを細かく制御できます。
serializeメソッドは、オブジェクトの状態を正確に表す文字列を返す必要があります。この返された文字列は、後にunserialize()関数を使ってオブジェクトを元の状態に戻す(デシリアライズする)際に利用されます。したがって、このメソッドが返す文字列には、オブジェクトを完全に再構築するために必要なすべての情報が含まれている必要があります。
PHP 8以降では、オブジェクトのシリアライズをより柔軟に行うための__serialize()マジックメソッドが導入され、推奨される方法となっていますが、Serializableインターフェースとそのserializeメソッドも引き続き利用可能です。Serializableインターフェースを利用する際には、このserializeメソッドと、オブジェクトを復元するunserializeメソッドの両方を必ず実装する必要があります。
構文(syntax)
1<?php 2 3class MyClass implements Serializable 4{ 5 private string $property; 6 7 public function __construct(string $value) 8 { 9 $this->property = $value; 10 } 11 12 public function serialize(): string 13 { 14 // オブジェクトの状態を表す文字列を返します。 15 // ここでは、プライベートプロパティをPHPの組み込みserialize関数で文字列化しています。 16 return serialize($this->property); 17 } 18 19 // Serializableインターフェースを実装する場合、unserializeメソッドも必要ですが、 20 // ここではserializeメソッドの構文に焦点を当てているため省略します。 21 // public function unserialize(string $data): void 22 // { 23 // $this->property = unserialize($data); 24 // } 25}
引数(parameters)
引数なし
引数はありません
戻り値(return)
string
このメソッドは、オブジェクトの現在の状態をシリアライズした文字列を返します。この文字列は、後で unserialize() メソッドを使用して元のオブジェクトに復元できます。
サンプルコード
PHP serialize_precisionによる精度制御
1<?php 2 3/** 4 * MySerializableClass は Serializable インターフェースを実装し、 5 * オブジェクトのカスタムシリアライズ/デシリアライズロジックを提供します。 6 * 7 * 注意: PHP 8 では Serializable インターフェースは非推奨 (deprecated) です。 8 * 代わりに __serialize() および __unserialize() マジックメソッドの使用が推奨されます。 9 * このサンプルコードは、リファレンス情報に基づき Serializable インターフェースを使用しています。 10 */ 11class MySerializableClass implements Serializable 12{ 13 private float $value; 14 private string $name; 15 16 public function __construct(float $value, string $name) 17 { 18 $this->value = $value; 19 $this->name = $name; 20 } 21 22 public function getValue(): float 23 { 24 return $this->value; 25 } 26 27 public function getName(): string 28 { 29 return $this->name; 30 } 31 32 /** 33 * オブジェクトの内部状態をシリアライズ可能な文字列として返します。 34 * 35 * このメソッドの実装では、PHPの標準のserialize()関数を使用して 36 * オブジェクトのプロパティをシリアライズしています。 37 * PHPのini設定 'serialize_precision' は、この内部のserialize()関数が 38 * 浮動小数点数を文字列に変換する際の精度に影響を与えます。 39 * 40 * @return string シリアライズされたオブジェクトデータ 41 */ 42 public function serialize(): string 43 { 44 // オブジェクトのプロパティを配列にまとめ、PHPの標準serialize関数でシリアライズ。 45 // このステップで 'serialize_precision' の影響を受けます。 46 return serialize([ 47 'value' => $this->value, 48 'name' => $this->name, 49 ]); 50 } 51 52 /** 53 * シリアライズされた文字列からオブジェクトの状態を復元します。 54 * 55 * @param string $data serialize() メソッドによって生成されたデータ 56 * @return void 57 */ 58 public function unserialize(string $data): void 59 { 60 // unserialize() 関数でデータからプロパティを復元 61 $unserializedData = unserialize($data); 62 $this->value = $unserializedData['value']; 63 $this->name = $unserializedData['name']; 64 } 65} 66 67// ----------------------------------------------------------- 68// 以下は、MySerializableClass と php serialize_precision の関連性を示すコード例です。 69// ----------------------------------------------------------- 70 71// 非常に長い小数を含む浮動小数点数を用意します。 72$myFloat = 123.4567890123456789; 73$myObject = new MySerializableClass($myFloat, "Sample Item"); 74 75echo "元の浮動小数点数: " . sprintf("%.20f", $myFloat) . "\n\n"; 76 77echo "--- PHPのini設定 'serialize_precision' の影響を確認 ---\n\n"; 78 79// 1. デフォルトの serialize_precision の場合 80// PHP 8 のデフォルトは通常 17 です。 81echo "1. デフォルトの serialize_precision (" . ini_get('serialize_precision') . "):\n"; 82// オブジェクトをシリアライズします。この際、MySerializableClass::serialize() が内部で呼ばれます。 83$serializedDataDefault = serialize($myObject); 84echo " シリアライズデータ: " . $serializedDataDefault . "\n"; 85// シリアライズデータをデシリアライズして、元のオブジェクトを復元します。 86$unserializedObjectDefault = unserialize($serializedDataDefault); 87// 復元された浮動小数点数を表示(20桁まで) 88echo " デシリアライズ後の値: " . sprintf("%.20f", $unserializedObjectDefault->getValue()) . "\n\n"; 89 90// 2. serialize_precision を低く設定 (例: 8) 91ini_set('serialize_precision', '8'); 92echo "2. serialize_precision を 8 に設定した場合:\n"; 93// 再度オブジェクトをシリアライズします。ini設定が変更されたため、浮動小数点数の精度が変わります。 94$serializedDataLowPrecision = serialize($myObject); 95echo " シリアライズデータ: " . $serializedDataLowPrecision . "\n"; 96$unserializedObjectLowPrecision = unserialize($serializedDataLowPrecision); 97echo " デシリアライズ後の値: " . sprintf("%.20f", $unserializedObjectLowPrecision->getValue()) . "\n\n"; 98 99// 3. serialize_precision を高く設定 (例: 20) 100ini_set('serialize_precision', '20'); 101echo "3. serialize_precision を 20 に設定した場合:\n"; 102// 更に高い精度でシリアライズします。 103$serializedDataHighPrecision = serialize($myObject); 104echo " シリアライズデータ: " . $serializedDataHighPrecision . "\n"; 105$unserializedObjectHighPrecision = unserialize($serializedDataHighPrecision); 106echo " デシリアライズ後の値: " . sprintf("%.20f", $unserializedObjectHighPrecision->getValue()) . "\n\n"; 107 108// 元の serialize_precision 設定に戻します (推奨) 109ini_restore('serialize_precision'); 110 111?>
このコードは、PHPのSerializableインターフェースとそのserialize()メソッドの動作を示しています。Serializable::serialize()メソッドは、オブジェクトの現在の状態を保存したり転送したりできる文字列形式に変換する役割を持ちます。このメソッドは引数を取らず、オブジェクトのデータが表現されたstringを戻り値として返します。
サンプルコードのMySerializableClassでは、オブジェクトのプライベートなプロパティ(浮動小数点数valueと文字列name)を配列にまとめ、PHP標準のserialize()関数を使って文字列へと変換しています。ここで注目すべきは、PHPのini設定であるserialize_precisionです。この設定は、浮動小数点数をシリアライズする際に、どこまでの精度で文字列に変換するかを制御します。serialize_precisionの値が低いと、元の浮動小数点数が持つ細かい精度が失われ、シリアライズ後にデシリアライズすると元の値と異なる結果になる可能性があります。
サンプルコードの後半では、serialize_precisionの値を変更しながらオブジェクトをシリアライズ・デシリアライズし、浮動小数点数の精度がどのように影響を受けるかを具体的に示しています。PHP 8ではSerializableインターフェースは非推奨であり、代わりに__serialize()と__unserialize()マジックメソッドの使用が推奨されていますが、このサンプルはリファレンス情報に基づきSerializableを使用しています。
PHP 8では、Serializableインターフェースは非推奨となっています。新規開発では__serialize()と__unserialize()というマジックメソッドの使用が推奨されますので、この点に十分ご注意ください。また、Serializable::serialize()メソッド内部で浮動小数点数をシリアライズする場合、PHPのini設定であるserialize_precisionがその精度に影響を与えます。この設定値が異なると、デシリアライズ時に元の浮動小数点数と異なる値が復元される可能性があります。したがって、浮動小数点数をシリアライズ・デシリアライズする際は、開発環境と本番環境でserialize_precisionの設定が一致しているか、または必要な精度を確保できる値になっているかを必ず確認してください。
PHPのSerializable::serialize()でオブジェクトをJSON化する
1<?php 2 3/** 4 * カスタムシリアライズ可能なユーザー情報を表すクラス。 5 * PHP 8ではSerializableインターフェースは非推奨です。 6 * 代わりに __serialize() と __unserialize() マジックメソッドの使用が推奨されます。 7 */ 8class User implements Serializable 9{ 10 private int $id; 11 private string $name; 12 private array $data; 13 14 /** 15 * Userクラスの新しいインスタンスを生成します。 16 * 17 * @param int $id ユーザーID 18 * @param string $name ユーザー名 19 * @param array $data ユーザーに関連する追加データ 20 */ 21 public function __construct(int $id, string $name, array $data = []) 22 { 23 $this->id = $id; 24 $this->name = $name; 25 $this->data = $data; 26 } 27 28 /** 29 * オブジェクトのカスタムシリアライズロジックを定義します。 30 * このメソッドは、オブジェクトのプロパティをJSON文字列に変換して返します。 31 * これにより、オブジェクトの状態をJSON形式で保存できます。 32 * 33 * @return string オブジェクトの状態を表すJSON文字列 34 */ 35 public function serialize(): string 36 { 37 // オブジェクトの重要なプロパティを連想配列にまとめます 38 $properties = [ 39 'id' => $this->id, 40 'name' => $this->name, 41 'data' => $this->data, 42 ]; 43 // 連想配列をJSON文字列にエンコードして返します 44 return json_encode($properties); 45 } 46 47 /** 48 * serialize() メソッドによって生成されたJSON文字列からオブジェクトを復元します。 49 * このメソッドは、unserialize()関数ではなく、クラス内部のロジックで呼び出されます。 50 * 51 * @param string $data serialize()から返されたJSON文字列 52 */ 53 public function unserialize(string $data): void 54 { 55 // JSON文字列をデコードして連想配列に戻します 56 $decoded = json_decode($data, true); 57 58 // JSONデコードに失敗した場合の基本的なエラー処理 59 if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) { 60 throw new InvalidArgumentException("無効なJSONデータが提供されました: " . json_last_error_msg()); 61 } 62 63 // デコードされたデータでオブジェクトのプロパティを復元します 64 $this->id = $decoded['id'] ?? 0; 65 $this->name = $decoded['name'] ?? 'Guest'; 66 $this->data = $decoded['data'] ?? []; 67 } 68 69 /** 70 * ユーザーIDを取得します。 71 * @return int 72 */ 73 public function getId(): int 74 { 75 return $this->id; 76 } 77 78 /** 79 * ユーザー名を取得します。 80 * @return string 81 */ 82 public function getName(): string 83 { 84 return $this->name; 85 } 86 87 /** 88 * ユーザーの追加データを取得します。 89 * @return array 90 */ 91 public function getData(): array 92 { 93 return $this->data; 94 } 95} 96 97// --- サンプルコードの実行 --- 98 99// 1. Userオブジェクトを作成します 100$user = new User(101, 'Taro Yamada', ['email' => 'taro@example.com', 'role' => 'member']); 101echo "元のオブジェクトの状態:\n"; 102echo "ID: " . $user->getId() . "\n"; 103echo "名前: " . $user->getName() . "\n"; 104echo "追加データ: " . json_encode($user->getData(), JSON_UNESCAPED_UNICODE) . "\n\n"; 105 106// 2. Serializable::serialize() メソッドを使用してオブジェクトをJSON文字列に変換します。 107// このメソッドが直接JSON形式の文字列を生成します。 108$jsonString = $user->serialize(); 109echo "serialize() が生成したJSON文字列:\n"; 110echo $jsonString . "\n\n"; 111 112// 3. unserialize() メソッドを使用してJSON文字列からオブジェクトを復元します。 113// 新しいオブジェクトを作成し、そのunserialize()メソッドにJSON文字列を渡すことで状態を復元します。 114$restoredUser = new User(0, ''); // 復元用の仮の初期値を持つオブジェクト 115$restoredUser->unserialize($jsonString); 116 117echo "unserialize() で復元されたオブジェクトの状態:\n"; 118echo "ID: " . $restoredUser->getId() . "\n"; 119echo "名前: " . $restoredUser->getName() . "\n"; 120echo "追加データ: " . json_encode($restoredUser->getData(), JSON_UNESCAPED_UNICODE) . "\n";
PHPのSerializable::serialize()メソッドは、オブジェクトの現在の状態を文字列に変換(シリアライズ)するために使われる特別なメソッドです。この機能は、オブジェクトの情報をファイルに保存したり、ネットワークを通じて他のシステムに送ったりする際に役立ちます。
このメソッドは引数を必要とせず、オブジェクトの内部データを表現する文字列を戻り値として返します。サンプルコードのUserクラスでは、serialize()メソッドが、ユーザーID、名前、追加データといったオブジェクトのプロパティをJSON形式の文字列に変換しています。これにより、複雑なオブジェクトの状態を簡潔なJSONデータとして出力し、後でそのJSONから元のオブジェクトを正確に復元(デシリアライズ)できるようにします。serialize()と対になるunserialize()メソッドを実装することで、オブジェクトの保存と復元のロジックをクラス内でカスタマイズすることが可能になり、オブジェクトをJSONとして扱いやすくなります。
このサンプルコードは、PHP 8で非推奨となったSerializableインターフェースを使用しています。現在では代わりに__serialize()と__unserialize()マジックメソッドの使用が推奨されるため注意してください。ここで定義されているserialize()メソッドは、オブジェクトのデータをPHP標準のserialize()関数とは異なり、カスタムでJSON形式の文字列に変換しています。これは、外部システムとのデータ連携などでJSONが必要な場合に特に有効です。また、unserialize()メソッドは、そのJSON文字列をデコードしてオブジェクトの状態を安全に復元します。データの整合性とセキュリティのため、復元時には必ず入力データの検証と適切なエラー処理を行うことが非常に重要です。