__serialize y __unserialize
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 49 de 91.
Cuando necesitas convertir un objeto en una cadena para su almacenamiento o transmisión, PHP utiliza la serialización. Los métodos mágicos __serialize() y __unserialize() te dan control sobre exactamente qué datos se guardan y cómo se restauran.
El método __serialize() devuelve un array de datos para ser serializados, mientras que __unserialize() recibe ese array y reconstruye el objeto:
<?php
class Session {
public function __construct(
private string $userId,
private array $data,
private int $createdAt
) {}
public function __serialize(): array {
return [
'userId' => $this->userId,
'data' => $this->data
];
}
public function __unserialize(array $data): void {
$this->userId = $data['userId'];
$this->data = $data['data'];
$this->createdAt = time();
}
public function getCreatedAt(): int {
return $this->createdAt;
}
}
$session = new Session("user123", ["theme" => "dark"], time());
$serialized = serialize($session);
$restored = unserialize($serialized);
echo "User: " . $restored->getCreatedAt();
Observa cómo createdAt se excluye de la serialización y obtiene una nueva marca de tiempo al ser deserializado. Esto es útil para excluir datos sensibles, valores temporales o recursos que no se pueden serializar, como las conexiones a bases de datos.
Estos métodos reemplazaron a los antiguos métodos __sleep() y __wakeup() en PHP 7.4, ofreciendo un enfoque más limpio donde trabajas directamente con arreglos de datos en lugar de nombres de propiedades.
Desafío
FácilVamos a construir un sistema de almacenamiento en caché de perfiles de usuario que demuestre cómo __serialize() y __unserialize() te dan el control sobre qué datos se guardan y cómo se restauran.
Organizarás tu código en dos archivos:
UserProfile.php— Crea una claseUserProfileque represente el perfil de un usuario con capacidades de almacenamiento en caché. Usa la promoción de constructor para definir propiedades privadas para$userId(string),$username(string),$email(string) y$accessToken(string). Añade una propiedad privada$cachedAtque almacene cuándo se guardó el perfil en caché (establécela como"not cached"inicialmente en el constructor). Tu clase necesita:__serialize()— Devuelve un array que contiene solo eluserId,usernameyemail. ElaccessTokenes sensible y nunca debe ser serializado. La marca de tiempocachedAtse regenerará al restaurar.__unserialize()— Restaura eluserId,usernameyemaildesde el array de datos. EstableceaccessTokencomo"expired"(ya que los tokens no deben persistir).getInfo()— Devuelve un string con el formato:"[username] ([email]) - Token: [accessToken] - Cached: [cachedAt]"
main.php— Incluye el archivo UserProfile. Recibirás cuatro entradas: un ID de usuario, un nombre de usuario, un correo electrónico y un token de acceso. Crea una instancia deUserProfilecon estos valores. Imprime tres líneas:- La información del perfil original (antes de la serialización)
- Serializa el perfil usando
serialize(), luego des-serialízalo usandounserialize()para crear un perfil restaurado. Imprime la información del perfil restaurado. - Imprime
"Token preserved: yes"o"Token preserved: no"dependiendo de si el token del perfil restaurado coincide con el original (pista: no debería coincidir ya que los tokens expiran al restaurar)
Este patrón es esencial para almacenar datos de usuario en caché de forma segura: quieres guardar la información del perfil pero nunca persistir credenciales sensibles como los tokens de acceso. Cuando el perfil se restaura desde la caché, el token se marca como expirado, obligando a la aplicación a obtener uno nuevo.
Hoja de referencia
Los métodos mágicos __serialize() y __unserialize() controlan qué datos se guardan durante la serialización y cómo se restauran los objetos.
__serialize() devuelve un array de datos para ser serializados:
<?php
public function __serialize(): array {
return [
'userId' => $this->userId,
'data' => $this->data
];
}__unserialize() recibe el array y reconstruye el objeto:
<?php
public function __unserialize(array $data): void {
$this->userId = $data['userId'];
$this->data = $data['data'];
$this->createdAt = time();
}Usa serialize() para convertir un objeto en una cadena y unserialize() para restaurarlo:
<?php
$serialized = serialize($session);
$restored = unserialize($serialized);Estos métodos son útiles para excluir datos sensibles, valores temporales o recursos que no se pueden serializar (como conexiones a bases de datos). Las propiedades pueden regenerarse con valores frescos durante la deserialización.
Pruébalo tú mismo
<?php
require_once 'UserProfile.php';
// Leer entradas
$userId = trim(fgets(STDIN));
$username = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$accessToken = trim(fgets(STDIN));
// TODO: Crear una instancia de UserProfile con los valores de entrada
// TODO: Imprimir la información del perfil original (antes de la serialización)
// TODO: Serializar el perfil, luego deserializarlo para crear un perfil restaurado
// TODO: Imprimir la información del perfil restaurado
// TODO: Imprimir "Token preserved: yes" o "Token preserved: no"
// dependiendo de si el token del perfil restaurado coincide con el original
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy