Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Tipos de datos personalizados

Nota

Este tutorial explica la implementación de tipos de datos personalizados utilizando el MongoDB\BSON\Persistable Interfaz que se encuentra en la extensión MongoDB. Considere usar un códec para desacoplar la lógica de persistencia de MongoDB de su lógica de negocio. Consulte Tutorial del códec para un ejemplo.

La extensión y biblioteca PHP de MongoDB admiten clases personalizadas durante la serialización y deserialización. Un ejemplo de su utilidad es almacenar información de fecha y hora conservando la información de zona horaria que la clase DateTimeImmutable de PHP almacena con un punto en el tiempo.

La extensión serializa variables PHP, incluidos objetos, en BSON cuando se comunica con el servidor, y deserializa BSON de nuevo a variables PHP cuando recibe datos del servidor.

Es posible influir en el comportamiento mediante la implementación de la interfaz de MongoDB\BSON\Persistable. Si una clase implementa esta interfaz, al momento de la serialización se llama al método bsonSerialize. Este método es responsable de devolver un arreglo o un objeto stdClass para convertirlo a BSON y almacenarlo en la base de datos. Estos datos se utilizarán posteriormente para reconstruir el objeto al leer desde la base de datos.

Como ejemplo presentamos el LocalDateTime clase. Esta clase envuelve el tipo de datos MongoDB\BSON\UTCDateTime y una zona horaria.

<?php
/* 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;
}
?>

Dado que implementa la interfaz MongoDB\BSON\Persistable, la clase debe implementar los métodos bsonSerialize y bsonUnserialize. En el método bsonSerialize, devolvemos una matriz con los dos valores que necesitamos conservar: el punto temporal en milisegundos desde la época, representado por un objeto MongoDB\BSON\UTCDateTime, y una cadena que contiene el identificador de la zona horaria de Olson:

<?php
public function bsonSerialize()
{
return [
'utc' => $this->utc,
'tz' => $this->tz->getName(),
];
}
?>

La extensión añadirá además un campo __pclass al documento y lo almacenará también en la base de datos. Este campo contiene el nombre de la clase PHP para que al deserializar la extensión sepa qué clase usar para recrear el objeto almacenado.

Cuando se lee el documento desde la base de datos, la extensión detecta si __pclass hay un campo y luego ejecuta el método MongoDB\BSON\Persistable::bsonUnserialize, que es responsable de restaurar el estado original del objeto.

En el código siguiente, nos aseguramos de que los datos de los campos utc y tz sean del momento correcto y luego asignamos sus valores a las dos propiedades privadas.

<?php
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']);
}
?>

Puede que hayas notado que la clase también implementa la interfaz MongoDB\BSON\UTCDateTimeInterface. Esta interfaz define los dos métodos no constructores de la clase MongoDB\BSON\UTCDateTime.

Se recomienda que los contenedores de las clases BSON existentes implementen la interfaz correspondiente (es decir, MongoDB\BSON\UTCDateTimeInterface) para que los objetos contenedor puedan usarse en el mismo contexto que sus versiones originales sin envolver. También se recomienda que siempre se utilicen sugerencias de tipo para la interfaz (es decir, MongoDB\BSON\UTCDateTimeInterface) y nunca para la clase concreta (es decir, MongoDB\BSON\UTCDateTime), ya que esto impediría que los objetos envueltos sean aceptados en los métodos.

En nuestro nuevo método toDateTime, devolvemos un objeto DateTime con la zona horaria local establecida, en lugar del UTC que normalmente utiliza MongoDB\BSON\UTCDateTime en su valor de retorno.

<?php
public function toDateTime()
{
return $this->utc->toDateTime()->setTimezone($this->tz);
}
public function __toString()
{
return (string) $this->utc;
}
}
?>

Con la clase definida, ahora podemos usarla en nuestros documentos. El siguiente fragmento muestra el ida y vuelta desde el objeto LocalDateTime a BSON, y de regreso a LocalDateTime.

<?php
$bson = MongoDB\BSON\Document::fromPHP(['date' => new LocalDateTime]);
$document = $bson->toPHP();
var_dump($document);
var_dump($document->date->toDateTime());
?>

¿Qué resultados:

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"
}

Almacenar el identificador de zona horaria de Olson en un campo separado también funciona bien con el Marco de Agregación de MongoDB, que permite la manipulación de fechas, formateo y consultas dependiendo de una zona horaria específica.

Volver

Agregación