Implementando Serialización Personalizada con `__sleep` y `__wakeup` en PHP
La serialización en PHP permite convertir objetos en una cadena de bytes para su almacenamiento o transmisión. Aunque `serialize()` y `unserialize()` son funciones convenientes, a veces necesitamos un control más fino sobre qué propiedades se serializan y cómo se reconstruyen los objetos. Las funciones mágicas `__sleep()` y `__wakeup()` ofrecen este control, permitiendo la serialización personalizada.
El método `__sleep()` permite especificar un array de nombres de propiedades que deben ser serializadas. Si no se define, todas las propiedades del objeto serán serializadas. `__wakeup()` se ejecuta durante la deserialización y puede usarse para reestablecer conexiones de base de datos, recursos, o realizar cualquier inicialización necesaria.
class DatabaseConnection {
private $host, $username, $password, $connection;
public function __construct($host, $username, $password) {
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect() {
$this->connection = mysqli_connect($this->host, $this->username, $this->password);
if (!$this->connection) {
die("Connection failed: " . mysqli_connect_error());
}
}
public function query($sql) {
return mysqli_query($this->connection, $sql);
}
public function __sleep() {
// No serializamos la conexión directamente
return array('host', 'username', 'password'); // Solo serializamos los datos para reconectar
}
public function __wakeup() {
// Reconectamos a la base de datos cuando se deserializa el objeto
$this->connect();
}
public function __destruct() {
if($this->connection){
mysqli_close($this->connection);
}
}
}
// Ejemplo de uso
$db = new DatabaseConnection("localhost", "user", "password");
$serialized = serialize($db);
// Destruimos el objeto original para simular la pérdida de la conexión
unset($db);
// Deserializamos el objeto. __wakeup() se ejecutará aquí.
$db = unserialize($serialized);
// Ahora podemos usar la conexión deserializada
$result = $db->query("SELECT 1");
if ($result) {
echo "Conexión restablecida y consulta exitosa!\n";
}
En este ejemplo, la conexión de base de datos (`$this->connection`) no se serializa directamente. En su lugar, `__sleep()` solo guarda la información necesaria para reconectar. Durante la deserialización, `__wakeup()` crea una nueva conexión, asegurando que el objeto deserializado pueda continuar funcionando correctamente. La inclusion de `__destruct()` asegura que al destruir una instancia, la conexion sea cerrada.
// Otro ejemplo simple para ilustrar __sleep con menos dependencias.
class User {
public $username;
private $password;
private $token;
public function __construct($username, $password) {
$this->username = $username;
$this->password = $password;
$this->token = bin2hex(random_bytes(16)); // Genera un token aleatorio
}
public function __sleep() {
// No serializamos el password ni el token
return ['username']; // Solo serializamos el username
}
}
$user = new User("testuser", "secret");
$serialized_user = serialize($user);
echo $serialized_user;
El ejemplo del Usuario demuestra una forma de proteger informacion sensible al no ser almacenada al serializar el objeto.
El uso de `__sleep()` y `__wakeup()` proporciona un mecanismo robusto para controlar el proceso de serialización, especialmente útil cuando se trabaja con recursos externos, información sensible o estados complejos dentro de los objetos.
No hay comentarios:
Publicar un comentario