Serialización de clases en PHP4
(QR Code)Anteriormente ya había hablado de la programación orientada a objetos en PHP4, ahora vamos a ir complementado con la serialización de clases.
En PHP las clases se pueden serializar en una cadena de datos mediante la función serialize de PHP, la cual convierte los datos de nuestra clase en una cadena de valores.
Así mismo las clases serializadas se pueden volver a recuperar con la función unserialize devolviendo los valores de la clase otra vez a la misma para recuperar su estado.
Hasta aquí todo bien, pero que pasa si queremos realizar alguna función extra, o por ejemplo que nuestra clase se conecte con una base de datos y queramos restaurar el recurso de la conexión, ya que aunque tengamos la variable que indica el recurso del enlace de conexión este no seguirá activo. Pues bien, que no cunda el pánico, ya que hay unas funciones “mágicas” para ello en PHP que nos permiten hacer operaciones antes de serializar y después de serializar, con las que podemos guardar información a las variables globales y preparar nuestra clase para serializarse con todos los parámetros que necesitemos, y para después volver a restaurar correctamente la clase.
Antes de serializar usando la clase con serialize, si se trata de una clase, PHP llamara a la función mágica __sleep() de nuestra clase (que nosotros crearemos), en ella haremos todas las operaciones que necesitemos grabando los datos en variables de la clase, y posteriormente se serializara dicha clase.
Por el contrario al restaurar la clase con unserialize, este restaurara primero los valores de las variables y procederá a llamar (si existe) a la función __wakeup() para que realice el proceso que se requiera para la restauración de la clase.
Un ejemplo de una clase de conexión serializable.
class Connection {
var $link;
var $server;
var $username;
var $password;
var $db;
public function Connection($server, $username, $password, $db){
$this->server = $server;
$this->username = $username;
$this->password = $password;
$this->db = $db;
$this->connect();
}
private function connect(){
$this->link = mysql_connect($this->server, $this->username, $this->password);
mysql_select_db($this->db, $this->link);
}
public function __sleep(){
mysql_close($this->link);
}
public function __wakeup(){
$this->connect();
}
}
Un ejemplo de la serialización y guardado en un archivo de una clase
// Creamos nuestra clase de conexion
$con = new Conexion("localhost","root","root","test");
// Serializamos nuestra clase
$miClaseparaGuardar = serialize($con);
// guardamos en un archivo la clase
$gestor = fopen("clase.txt", 'a'));
fwrite($gestor, $miClaseparaGuardar );
fclose($gestor);
Y un ejemplo de como recuperamos la clase anteriormente serializada
// Recuperamos los datos de la clase
$gestor = fopen("clase.txt", 'r'));
$contenido = fread($gestor, filesize("clase.txt"));
fclose($gestor);
// Volvemos a su estado la clase. (debe existir la definición de la clase lógicamente xD)
$con = unserialize($con);









uhmm.. muy bueno eh .. mira yo recien estoy empezando a manejar php .. y
me interesa muxo el tema de persistencia ..
ahora ..como sabras o como creo q veo tu codigo solo hace para guardar una sola vez ..
si necesito guardar mas objetos de tipo Conexion .. como lo haria ?? y como lo recueperia
todos los ebjestos guardados… te agradeceria tu respuesta ^^;
28/02/2008 6:00
Esto realmente se trata de un “Mini” ejemplo de la funcionalidad de __wakeup y __sleep.
Una clase en PHP al ser serializada lo que hace es guardar todos sus valores internos en una cadena con un formato que luego pueda recuperar, y al deserializar dicho objecto implemente crea esa instancia y vuelve a obtener esos valores.
Si lo que te interesa es la persistencia de datos entre paginas en PHP te recomiendo que mires “Sesiones” (session_start(); session_destroy(); $_SESSION[] … etc ) , La sesión es un “contenedor” de “objetos” para todo el tiempo que un usuario este navegando por dicha web. Ttambién si lo que quieres es guardar datos de un usuario, lo mas practico es el uso de bases de datos (muy común el uso de MySQL).
En este caso particular, si tienes mas de un objeto conexion, y quieres salvarlos puedes hacerlo en multiples archivos, o bien, sabiendo que lo que te devuelve el metodo serialize es una cadena, puedes crear un Array , serializarlo a su vez y guardarlo en un archivo.
Ej:
$con1 = new Conexion(“localhost”,”root”,”root”,”test1″);
$con2 = new Conexion(“localhost”,”root”,”root”,”test2″);
$conexiones = Array();
$conexiones[] = serialize($con1);
$conexiones[] = serialize($con2);
// Guardado
$gestor = fopen(“clases.txt”, ‘a’));
fwrite($gestor, $miClaseparaGuardar );
fclose($gestor);
// Recuperacion
$gestor = fopen(“clases.txt”, ‘r’));
$conexiones_string = fread($gestor, filesize(“clase.txt”));
fclose($gestor);
$conexiones_array = unserialize($conexiones_string);
$con1 = unserialize($conexiones_array[0]);
$con2 = unserialize($conexiones_array[1]);
28/02/2008 9:18
^^; Gracias Kuroneko por la respuesta … Disculpa sin soy cargoso ..pero .. mira el sgt codigo
java … creo q asi entenderas a lo que va mi pregunta
CLASE MiObjectOutputStream
Pckage jpackClases
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io. OutputStream;
public class MiObjectOutputStream extends OutputStream
{
/*Constructor que recibe un OutputStream*/
public MiObjectOutputStream(OutputStream out ) throws IOException
{
super(out);
}
/*Constructor sin parametros*/
protected MiObjectOutputStream() throws IOException,SecurityException
{
super();
}
protected void writeStreamHeader() throws IOException
{
}
}
/*********************************************************************/
CLASE Alumno
import java.io.*;
public class Alumno Implements Serializable
{
private String codigo;
private String nombre;
private int promedio;
public Alumno()
{
this,codigo = 123;
this.nombre = “Juan Perezâ€;
this.promedio = 20;
}
//metodos Set y get
}
CLASE Inicio
import java.io.*;
public class Inicio
{
public Alumno IngresarDatosAlumno()
{
Alumno A = new Alumno();
String dato;
int numero;
Base.mostrar(“========================â€);
Base.mostrar(“Registro de datos del Alumnoâ€);
Base.mostrar(“========================â€);
do
{
Base.mostrar(“Ingrese Código del Alumnoâ€);
dato = Base.leerdato();
}while(dato.length() ==0);
A.setCodigo(dato);
do
{
Base.mostrar(“Ingrese Nombre del Alumnoâ€);
dato = Base.leerdato();
}while(dato.length() ==0);
A.setNombre(dato);
do
{
Base.mostrar(“Ingrese Promedio del Alumnoâ€);
numero = Base.convertirEntero( Base.leerdato());
}while(numero20);
A.setPromedio(numero);
return A;
}
Public void crearArchivoAlumno()
{
Alumno A = IngresarDatosAlumno();
try
{
ObjectOutputStream salida = new ObjectOutputStream(new FileOutputStream(“alumno.datâ€) )
salida.writeObject(A);
salida.close();
}catch(IOException e)
{
Base.mostrar(“Error en la E/S del archivoâ€);
}
Base.mostrar(“Archivo Ingresado con Exitoâ€);
}
Public void añadirArchivoAlumno()
{
Alumno A = IngresarDatosAlumnos();
try
{
MiObjectOutputStream salida = new MiObjectOutputStream(new FileOutputStream(“alumno.datâ€,true ) )//true indika que esta abierto !!
salida.writeUnshared(A);
salida.close();
}catch(IOException e)
{
Base.mostrar(“Error en la E/S del archivoâ€);
}
}
Public void mostrarDatosAlumnos()
{
try
{
ObjectInputStream entrada = new ObjectInputStream(new FileInputStream(“alumnos.datâ€));
Alumno A;
pintarCabecera();
while((A = (Alumno)entrada.readObject())!= null)
{
pintarLineaCuerpo(A);
}
entrada.close();
}catch(EOFException e)
{
Base.mostrar(“Fin de Archivoâ€);
}catch(ClassNotFoundException e)
{
Base.mostrar(“Clase No Encontradaâ€);
}catch(IOException e)
{
Base.mostrar(“Error al leer el archivo..â€)
}
pintarPie();
}
public void pintarCabecera(Alumno A)
{
String dato,cadena;
int longitud,i;
dato = A.getCodigo();
longitud = dato.length();
if(longitud<10)
{
for(i=0;i<10-longitud;i++)
{
dato = dato + “ â€;
}
}
else
{
dato = dato.substring(0,10);
}
cadena = dato; // Ingresa a cadena el dato ..
dato = A.getNombre();
longitud = dato.length();
if(longitud<20)
{
for(i=0;i<20-longitud;i++)
{
dato = dato + “ â€;
}
}
else
{
dato = dato.substring(0,20);
}
cadena = cadena + “ â€+ dato;
dato = “ †+ A.getNombre();
longitud = dato.length();
if(longitud<10)
{
for(i=0;i<10-longitud;i++)
{
dato = dato + “ â€;
}
}
else
{
dato = dato.substring(0,10);
}
cadena = cadena +†â€+ dato;
Base.mostrar(cadena);
}
Public void mostrarMenu()
{
int opcion;
do
{
do
{
Base.mostrar(“============================â€);
Base.mostrar(“ MENU );
Base.mostrar(“============================â€);
Base.mostrar(“Crear Un Archivo de Alumnos……..[1]â€);
Base.mostrar(“Añadir un Alumno al Archivo………[2]â€);
Base.mostrar(“Mostrar Archivo de Alumnos ………[3] â€);
Base.mostrar(“Salir del Programa …………………[4]â€);
Base.mostrar(“Ingrese Su Opcion…:â€);
opcion= Base.convertirEntero(Base.leerDato());
}while(opcion4 );
switch(opcion)
{
case 1: crearArchivoAlumno();
break;
case 2 : añadirArchivoAlumno();
break;
case 3 : mostrarDatosAlumnos();
break;
}
} while(opcion!=4);
}
public static void main(String args[])
{
Inicio I = new Inicio();
I.mostraMenu();
}
}
Mira .. Mi primera duda.. es que si pudiese hacer en php . una funcion tipo (salida.writeUnshared)
del metodo Añadir archivo ..debes saber que este metodo insertar un alumno mas ..pero cuando
esta abierto .. linea mas arriba indica con true pa que sea abierto el archivo ..Luego en el metodo
(mostrarDatosAlumnos ) hay un while((A = (Alumno)entrada.readObject())!= null).. esas dos partes
me confunden para la implementacion en php …!! osea quiero saber si es posible ..de alguna maner a de forma dinamika ..
el ingreso y la salida de datos..sin utilizar $con1 = unserialize($conexiones_array[0]);
$con2 = unserialize($conexiones_array[1]); es que me imagino que si fuera unso 100 alumnos jeje ..
28/02/2008 10:03
Me parece que lo primero que hay aqui es un fallo de enfoque. No puedes pensar en PHP como en java.
Son lenguajes muy muy dispares. PHP Esta orientado a la programación en Web, y se trata de un lenguaje interpretado (el servidor lee un archivo php, lo ejecuta, y termina.) Mientras que java es un lenguaje mucho mas complejo y orientado a múltiples propósitos.
Deberías olvidar todos lo que sabes de JAVA y empezar con PHP desde la base ya que NO TIENEN NADA QUE VER.
un ejemplo claro es que las variables de PHP son “cualquier cosa”
Si yo hago $a = 1; es int y si luego hago $a=”1″ es String, pero nunca se declara su tipo.
en php cualquier cosa que no este entre < ?php y ?> sera printada en el navegador directamente, los archivos de por si no son “PHP” en su totalidad, si no que hay PHP y HTML.
Asi mismo los objetos de PHP no están orientados a ser contenedores, ni el sistema de archivos a almacenar datos. Ya que es una tecnología orientada a la programación Web en servidores, lo normal es guardar los datos en una base de datos, y tener una Conexión con esa base de datos (Una solo) que ejecute consultas para obtener los datos que se quieran.
En fin, el problema al que te enfrentas a mi parecer , es el desconocimiento de PHP y que intentas usarlo como en JAVA, pero esto no es posible, debes buscar un enfoque nuevo y una nueva forma de pensar.
Te recomiendo que busques algún tutorial web completo de como empezar con PHP, sobretodo que hable sobre como conectarse a una base de datos y hacer operaciones con SQL (el lenguaje de conexión con bases de datos)
28/02/2008 10:17
Gracias .. pues . si tienes toda la razon ..como te dije en lineas arriba recien empiezo en php
.. y si .. tengo que leer tutoriales.. gracias por el consejo .. =)…Eres una tipazo !! Gracias men .=)
28/02/2008 19:38