注意
このチュートリアルでは、 MongoDB拡張機能にある MongoDB\ BSON \Peristable インターフェースを使用してカスタム データ型を実装する説明を説明します。 MongoDB永続化ロジックをビジネス ロジックから分離するには、代わりにコーデックの使用を検討してください。例については、 コーデックのチュートリアルを参照してください。
MongoDB PHP拡張機能とライブラリは、直列化と逆直列化中にカスタム クラスをサポートします。これが役立つ例は、PHP の DateTimeInsumableクラスが特定の点で保存するタイムゾーン情報を保持する日付や時刻情報を保存する場合です。
拡張機能は、サーバーと通信するときにオブジェクトを含む PHP 変数を BSON に直列化し、サーバーからデータを受信するときに BSON を PHP 変数に逆直列化します。
MongoDB\ BSON\Persistable インターフェースを実装することで、動作に影響を与えることができます。クラスがこのインターフェースを実装している場合、直列化時に bsonSerialize メソッドが呼び出されます。このメソッドは、 BSONに変換してデータベースに保存する配列または stdClassオブジェクトを返すのを担当します。そのデータは、後でデータベースからの読み取り時にオブジェクトを再構築するために使用されます。
例として、LocalDateTime
クラスを示します。このクラスは、 MongoDB\ BSON\UTCDateTimeデータ型と タイムゾーンをラップします。
/* Custom document class that stores a UTCDateTime and time zone and also * implements the UTCDateTime interface for portability. */ class LocalDateTime implements \MongoDB\BSON\Persistable, \MongoDB\BSON\UTCDateTimeInterface { private $utc; private $tz; public function __construct($milliseconds = null, \DateTimeZone $timezone = null) { $this->utc = new \MongoDB\BSON\UTCDateTime($milliseconds); if ($timezone === null) { $timezone = new \DateTimeZone(date_default_timezone_get()); } $this->tz = $timezone; }
MongoDB\ BSON\Perstable インターフェースを実装するため、クラスはbsonSerialize および bsonUnserialize メソッドを実装するために必要です。 bsonSerialize メソッドでは、永続化する必要がある 2 つの値を含む配列を返します。つまり、 MongoDB\ BSON$UTCDateTimeオブジェクトで表される、UNIXエポックからのミリ秒単位の点と、Olson タイムゾーン識別子を含む string です。
public function bsonSerialize() { return [ 'utc' => $this->utc, 'tz' => $this->tz->getName(), ]; }
この拡張機能により、ドキュメントに__pclass
フィールドが追加され、それもデータベースに保存されます。 このフィールドには PHP クラス名が含まれているため、逆直列化時に拡張機能は保存されたオブジェクトの再作成に使用するクラスを認識できます。
ドキュメントがデータベースから読み取られると、拡張機能は__pclass
フィールドが存在するかどうかを検出し、オブジェクトの元の状態を復元するのに担当するMongoDB\ BSON\Persistable::bsonUnserialize メソッドを実行します。
以下のコードでは、 フィールドとutc
tz
フィールドのデータが正しいタイミングであることを確認し、その値を 2 つのプライベートプロパティに割り当てます。
public function bsonUnserialize(array $data) { if ( ! isset($data['utc']) || ! $data['utc'] instanceof \MongoDB\BSON\UTCDateTime) { throw new Exception('Expected "utc" field to be a UTCDateTime'); } if ( ! isset($data['tz']) || ! is_string($data['tz'])) { throw new Exception('Expected "tz" field to be a string'); } $this->utc = $data['utc']; $this->tz = new \DateTimeZone($data['tz']); }
クラスがMongoDB\ BSON\UTCDateTimeInterface インターフェースも実装していることに注意してください。このインターフェースは、 MongoDB\ BSON\UTCDateTimeクラスの 2 つの非コンストラクター メソッドを定義します。
既存のBSONクラスを囲むラッパーは、それぞれのインターフェース( MongoDB\ BSON\UTCDateTimeInterface )を実装して、ラッパーオブジェクトを元のラップされていないバージョンと同じコンテキストで使用できることをお勧めします。また、ラップさクラスBSONオブジェクトがメソッドに受け入れられなくなります。
新しいtoDateTime
メソッドでは、 MongoDB\ BSON \UTCDateTime が戻り値で通常使用する UTC タイムゾーンではなく、ローカル タイムゾーンセットを持つ DateTimeオブジェクトが返されます。
public function toDateTime() { return $this->utc->toDateTime()->setTimezone($this->tz); } public function __toString() { return (string) $this->utc; } }
クラスが定義されたため、ドキュメント内で使用できるようになりました。 以下のスニペットは、 LocalDateTime
オブジェクトから BSON に、 LocalDateTime
に戻るラウンドトリップを示しています。
$bson = MongoDB\BSON\Document::fromPHP(['date' => new LocalDateTime]); $document = $bson->toPHP(); var_dump($document); var_dump($document->date->toDateTime());
その出力は次のとおりです。
object(stdClass)#1 (1) { ["date"]=> object(LocalDateTime)#2 (2) { ["utc":"LocalDateTime":private]=> object(MongoDB\BSON\UTCDateTime)#3 (1) { ["milliseconds"]=> string(13) "1533042443716" } ["tz":"LocalDateTime":private]=> object(DateTimeZone)#4 (2) { ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/London" } } } object(DateTime)#5 (3) { ["date"]=> string(26) "2018-07-31 14:07:23.716000" ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/London" }
Olson タイムゾーン識別子を別の フィールドに保存することも MongoDB の集計フレームワークと連携し、特定のタイムゾーンに応じて日付操作、形式、 クエリ が可能になります。