Cannot change save handler when session is active

Introducción

Trabajando en un pequeño proyecto de PHP me topé con la siguiente advertencia: Warning: session_set_save_handler(): Cannot change save handler when session is active. Este mensaje me tuvo dando vueltas por todo internet sin encontrar una solución, pero probando algunas cosas di con ella y vengo a exponerla.

PHP permite implementar nuestro propio manejador de sesiones. En este blog ya hemos hecho alguno anteriormente, justo aquí: implementar session handler en PHP.

Pues  bien, vamos a la solución y explicación.

Explicación de Cannot change save handler when session is active

El mensaje lo dice todo. No se puede cambiar el manejador de sesiones mientras la sesión está activa. Esto tiene bastante sentido.

Es decir, no podemos hacer esto:

<?php
session_start();
session_set_save_handler(/*El handler aquí*/);
$_SESSION["foo"] = "bar";
echo $_SESSION["foo"];
?>

Ya que como vemos, estamos llamando a session_start y después estamos llamando a session_set_save_handler. Por lo que primero debemos llamar a session_set_save_handler y luego utilizar la sesión.

Pero el problema no es así de simple, ya que, ¿Qué pasa cuando leemos dos veces la sesión? por ejemplo, puede que tengamos dos métodos que leen la sesión, y que se ejecuten uno después del otro. La llamada de las sesiones sería así:

<?php

/*
Esto genera un error de que la sesión ya ha sido iniciada pero este no es el
problema ahora, eso se soluciona con session_status y bla bla
*/

#--Esto lo hace el primer método
session_set_save_handler(/*El handler*/);
session_start();
$_SESSION["foo"] = "bar";
#Hasta aquí todo bien

#--Esto lo hace el segundo método

/*
Justo aquí abajo está el error...
la sesión está siendo leída o escrita, porque la iniciamos allá arriba
pero estamos intentando registrar un handler, y por eso
se genera la advertencia, pues no se puede registrar un handler mientras
leemos o escribimos
*/
session_set_save_handler(/*El handler*/);
session_start();
$_SESSION["foo"] = "bar";
#Hasta aquí todo bien

?>

El huevo o la gallina

Y aquí entramos en un dilema. La solución más fácil sería ver si no hay datos de sesión, y si  no los hay, entoncesregistramos el handler. Algo así:

<?php
if(!isset($_SESSION["bla"])) session_set_save_handler(/*Handler*/);
?>

¿Pero cómo leemos datos de sesión de nuestro handler, si no lo hemos registrado? y recordemos que si lo registramos, generará un error. Pero si no lo registramos, no podremos comprobar si ya ha sido registrado.

Analogía del huevo y la gallina con Warning: session_set_save_handler(): Cannot change save handler when session is active
Analogía del huevo y la gallina con Warning: session_set_save_handler(): Cannot change save handler when session is active

Se parece al problema del huevo y la gallina. Ya que si no registramos el handler, estaremos leyendo datos de sesión del manejador propio de PHP, no del nuestro. Pero no podemos registrar el handler porque genera un error. Error que evitamos leyendo datos de la sesión con el handler registrado.

Solución a Cannot change save handler when session is active

La solución es sencilla. Ya que no podemos registrar nuestro handler porque eso genera un error, pero para omitir el error debemos leer datos de la sesión de nuestro handler, podemos mejor comprobar si está definido el arreglo superglobal $_SESSION.

Dicho arreglo superglobal estará indefinido si no hay datos de sesion (independientemente del handler), así que podemos comprobarlo para ver si deberíamos o no registrar el manejador. Así:

<?php
if (!isset($_SESSION)){
  session_set_save_handler(/*El handler aquí*/);
}

De esta manera, no importa cuántas veces se llame a la sesión, pues el handler será registrado sólo una vez.

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

Dejar un comentario