Menu Docs
Página inicial do Docs
/ / /
Manual da Biblioteca PHP
/

Personalizar tipos de dados

Observação

Este tutorial explica a implementação de tipos de dados personalizados utilizando o MongoDB\BSON\Persistable interface encontrada na extensão MongoDB. Considere usar um codec para separar a lógica de persistência do MongoDB de sua lógica de negócios. Consulte o tutorial do codec para obter um exemplo.

A extensão e biblioteca MongoDB PHP oferecem suporte a classes personalizadas durante a serialização e desserialização. Um exemplo de onde isso pode ser útil é se você quiser armazenar informações de data/hora retendo as informações de fuso horário que o DateTimeImmutable do PHP armazenamentos de classe com um ponto no tempo.

A extensão serializa variáveis PHP, incluindo objetos, em BSON quando se comunica com o servidor e desserializa BSON de volta para variáveis PHP quando recebe dados do servidor.

É possível influenciar o comportamento implementando o MongoDB\BSON\Persistable interface. Se uma classe implementar essa interface, após a serialização o bsonSerialize o método é chamado. Este método é responsável por retornar uma array ou objeto stdClass para converter em BSON e armazenar no banco de dados. Esses dados serão posteriormente usados para reconstruir o objeto após a leitura do banco de dados.

Como exemplo apresentamos a classe LocalDateTime . Esta classe envolve o MongoDB\BSON\UTCDateTime tipo de dados e um fuso horário.

<?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;
}
?>

À medida que implementa o MongoDB\BSON\Persistable interface, a classe é necessária para implementar o bsonSerialize e bsonUnserialize métodos. No bsonSerialize método, retornamos uma array com os dois valores que precisamos persistir: o ponto no tempo em milissegundos desde a época, representado por um MongoDB\BSON\UTCDateTime objeto e uma string contendo o identificador de fuso horário Olson:

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

A extensão também adicionará um campo __pclass ao documento e o armazenará no banco de dados também. Este campo contém o nome da classe PHP para que, após a desserialização, a extensão saiba qual classe usar para recriar o objeto armazenado.

Quando o documento é lido a partir do banco de dados, a extensão detecta se um __pclass campo está presente e então executa MongoDB\BSON\Persistable::bsonUnserialize método que é responsável por restaurar o estado original do objeto.

No código abaixo, verificamos se os dados nos campos utc e tz são da hora certa e, em seguida, atribuímos seus valores às duas propriedades 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']);
}
?>

Você deve ter notado que a classe também implementa a interface MongoDB\BSON\UTCDateTimeInterface interface. Esta interface define os dois métodos não construtores do MongoDB\BSON\UTCDateTime aula.

É recomendável que os wrappers em torno das classes BSON existentes implementem sua respectiva interface (ou seja, MongoDB\BSON\UTCDateTimeInterface) para que os objetos do wrapper possam ser usados no mesmo contexto que sua versão original não envolvida. Também é recomendável que você sempre digite a dica na interface (ou seja, MongoDB\BSON\UTCDateTimeInterface) e nunca contra a classe específica (ou seja, MongoDB\BSON\UTCDateTime), pois isso impediria que objetos envoltos fossem aceitos em métodos.

Em nosso novo toDateTime método , retornamos uma data/hora objeto com o fuso horário local definido, em vez do fuso horário UTC que MongoDB\BSON\UTCDateTime normalmente usa em seu valor de retorno.

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

Com a classe definida, agora podemos usá-la em nossos documentos. O trecho abaixo demonstra a viagem de ida e volta do objeto LocalDateTime para BSON e de volta para LocalDateTime.

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

Quais saídas:

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

Armazenar o identificador de fuso horário Olson em um campo separado também funciona bem com a Estrutura de agregação do MongoDB, que permite manipulação de data, formatação e consulta, dependendo de um fuso horário específico.

Voltar

Executar comandos de banco de dados

Próximo

Decimal128