Programación orientada a objetos en PHP4

Constructores

Cada clase puede tener definido un método al que se llama cada vez que se crea una instancia de ella, utilizándose para configurar el estado inicial del objeto. En PHP este método debe tener el mismo nombre que la clase y al igual que con el resto de métodos, no se permite la sobrecarga, por lo que en el caso de necesitarla, será necesario emplear algún mecanismo similar al del punto anterior.

Un error muy frecuente al crear instancias de una clase, es la no utilización del operador referencia para capturar el resultado. Aún hoy hay multitud de ejemplos y aplicaciones escritas con declaraciones de instancia como $obj = new MyClass();, en la que se obtiene una copia de la instancia creada, desperdiciando recursos y pudiendo producirse errores inesperados en otras partes de la aplicación. En esta ocasión, al igual que en otras anteriores, lo mejor es aplicar la rutina de siempre crear las instancias de la misma forma, utilizando el operador referencia: $obj =& new MyClass();.

Sin embargo hay situaciones en las que no hay que aplicar el operador referencia para obtener la instancia de un objeto, esto ocurre dentro de los constructores en determinadas circunstancias, al manejar variables estáticas, o al intentar asignar una instancia a una variable global dentro de una función. Hay información al respecto de estas limitaciones en el manual de PHP en las páginas manejo de referencias dentro de los constructores y referencias con variables globales y estáticas. En cualquier caso el punto que más problemas suele causar es la asignación de instancias nuevas a variables globales dentro de una función, cosa que aunque pueda parecer no muy ortodoxa, es útil por ejemplo dentro de una clase encargada de configurar el contexto de ejecución de una página, creando todas las instancias de clases necesarias para su procesado.

<?php
 
 
$a = 'salida por defecto';
 
$v1 =& $a;
$v2 =& $a;
 
echo $a."\n";  // -> salida por defecto
echo $v1."\n"; // -> salida por defecto
echo $v2."\n"; // -> salida por defecto
 
$v2 = 'Salida modificada';
 
echo $a."\n";  // -> salida modificada
echo $v1."\n"; // -> salida modificada
echo $v2."\n"; // -> Salida modificada
 
 
?>

En el script anterior la llamada a test_global_ref no produce el resultado esperado, ya que la instancia creada no se asocia realmente a la variable global $obj. Para evitar este tipo de problemas, cuando haya que asignar instancias a variables globales la solución es sencilla y se basa en la utilización directa de la matriz de globales $GLOBALS

<?php
 
 
class Punto{
   var $x = 0;
   var $y = 0;
   function Punto($x, $y){
      $this->x = $x;
      $this->y = $y;
   }
}
 
class Ejemplo{
 
   function metodo1($p){
      $p->x = 123;
      $p->y = 123;
   }
 
   function metodo2(&$p){
      $p->x = 123;
      $p->y = 123;
   }
}
 
$punto =& new Punto(1,1);
 
print_r($punto);
 
Ejemplo::metodo1($punto);
print_r($punto);           // -> 1,1
 
 
Ejemplo::metodo2($punto);
print_r($punto);           // -> 123,123
 
 
?>

En esta ocasión al asignar la instancia directamente a la matriz de globales obtenemos el resultado deseado. Esto se debe a que al indicar global $obj; estamos realizando automáticamente una referencia sobre esa matriz y es lo que nos causa este tipo de problemas.

Serialización

La serialización es el proceso mediante el cual un objeto puede guardarse en un archivo, base de datos, o enviarse a través de una conexión de red. Deserialización es el proceso opuesto, en el que a partir de una información serializada se reconstruye una instancia de un objeto. PHP dispone de un par de funciones que permiten realizar las serializaciones y deserializaciones de una forma muy sencilla, serializa y unserialize. Estos métodos pueden trabajar con cualquier tipo de información, variables, arrays e incluso objetos. Serializar un objeto es un mecanismo que nos permite almacenar el estado de los objetos entre distintas peticiones, en una base de datos, en sesión, o en caché, y es utilizado habitualmente para evitar en parte el inconveniente de PHP referente a que no mantiene el estado entre peticiones. Por ejemplo, si tenemos una aplicación en la que en muchas peticiones es necesario crear un mimos objeto complejo, podríamos crearlo una primera vez, serializarlo y guardarlo en caché. En sucesivas peticiones el objeto sería deserializado en vez de regenerado desde cero.

PHP dispone de la opción de utilizar aparte dos métodos especiales en aquellas clases que queramos serializar, son __sleep y __wakeup. Hay situaciones en las que no conviene serializar todos los atributos de la clase, sino que querríamos indicar cuáles serializar y luego en la deserialización, a partir de ellos reconstruir el resto. Por ejemplo, en una clase que tenga como uno de sus atributos el handle a un archivo sobre el que van escribiendo los métodos, habría que serializar el nombre del archivo para que al reconstruir el objeto se pudiese volver a crear el handle.

<?php
 
 
class A{
   var $mensaje = "Clase A\n";
   function trace(){
      echo $this->mensaje;
   }
}
 
class B{
   var $a;
   var $mensaje = "Clase B\n";
   function B(){
      $this->a =& new A();
   }
   function trace(){
      echo $this->mensaje;
   }
   function getA(){
      return $this->a;
   }
   function& getA_2(){
      return $this->a;
   }
}
 
$b =& new B();
$a = $b->getA();
$a->mensaje = "modificado\n";
 
$a->trace();    // -> modificado
$b->trace();    // -> Clase B
$b->a->trace(); // -> Clase A
 
echo "\n\n";
 
$b2 =& new B();
$a2 =& $b2->getA_2();
$a2->mensaje = "modificado\n";
 
$a2->trace();    // -> modificado
$b2->trace();    // -> Clase B
$b2->a->trace(); // -> modificado
 
 
?>

En el anterior script se define una sencilla clase de Log, la cual consta de un atributo con el nombre del archivo sobre el que se escribe y un booleano que indica si está activado o no. En la serialización devolvemos un array con los nombres de los atributos que hay que serializar y en la deserialización, realizamos una llamada al método open, para que el estado del Log vuelva a ser como estaba antes de serializarlo.

Cuando deserializamos objetos es importante haber incluido antes el archivo con la definición de la clase, en otro caso la instancia se recuperará como de la clase stdClass, sin ningún método asociado.

Conclusiones

En los puntos anteriores he dado un repaso por las principales características que hay que tener en cuenta cuando programamos utilizando orientación a objetos en PHP4, manejor de referencias, paso de parámetros, ocultación de información, sobrecargas, constructores y serialización. Con las indicaciones aportadas es posible realizar aplicaciones orientadas a objetos evitando en gran medida los inconvenientes que tiene PHP4 con este paradigma de programación, teniendo únicamente claro cómo funciona cada cosa y marcándonos la rutina de hacer las cosas siempre de determinada forma para adquirir «buenas costumbres» y evitar fallos difíciles de encontrar a posteriori.

Páginas: 1 2 3

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

7 Respuestas para “Programación orientada a objetos en PHP4”

  1. Excelente clase de PHP.

    Muchas gracias.

  2. me parece estupendo el concepto que utiliza el autor de este articulo.felicitaciones!

  3. Muy buen documental, realmente.
    Perfectamente explicado y con ejemplos muy aclaratorios.

    Por otro lado, en el post Próximos artículos de PHP, indicabas como futura publicacion «Acceso a bases de datos». Estaría muy interesada en saber cuál sería una buena estructura de acceso a datos en una aplicación web en PHP4 basada en clases y objetos, y siguiendo el modelo MVC.

    Muchas gracias!

  4. ¡¡ Excelente exposicion !!
    Realmente de muy buen nivel, seguro de las cosas que hablas, las exlpicaciones de por qué referenciar un objeto (cuando lo creas), los tips.
    Muy claros ejemplos y su desarrollo.
    Mis felicitaciones.
    Saludos
    Gastón.

Trackbacks/Pingbacks

  1. Harlok.net - Mini curso de programacion a objetos en PHP4 - 06. Mar, 2006

    […] Dando un paseo por Google he visto un manual bastante claro de la programacion orientada a objetos con PHP4, esta en castellano y con sus ejemplos, aki teneis la direccion: http://www.eslomas.com/index.php/archives/2006/01/09/programacion-orientada-a-objetos-en-php4/1/ […]

  2. meneame.net - 23. Ago, 2006

    Programación orientada a objetos en PHP4

    El título lo dice todo. Ideal para todos aquellos que programamos en PHP4 y no tratamos mucho con sus objetos.

  3. EsLoMas.com » Serialización de objetos en PHP5 - 04. Ago, 2008

    […] Hace ya más de dos años hablé sobre ella en un extenso artículo dedicado a la programación orientada a objetos con PHP4. En esta ocasión voy a aportar un poco de luz sobre alguna característica peculiar de la serialización de objetos en PHP5. […]