Vídeo: PHP: ejemplo de página web con orientación a objetos (parte 2)
Descarga de ficheros del ejemplo: iDESWEB: PHP: ejemplo de página web con orientación a objetos
[kml_flashembed movie=”http://www.youtube.com/v/M-hlzCzw7TA” width=”560″ height=”315″ wmode=”transparent” /]
Transcripción:
Hola, soy Sergio Luján Mora, profesor de informática de la Universidad de Alicante, y en este vídeo que forma parte del curso “Introducción al desarrollo web”, te voy a mostrar un ejemplo de desarrollo de una página web con orientación a objetos.
En la primera parte de este vídeo, vimos un pequeño programa que estaba escrito con el estilo procedural y que trabajaba con datos almacenados en un array.
En esta segunda parte, voy a transformar ese código en orientado a objetos, con clases y objetos.
Algo muy importante en la programación orientada a objetos es el diseño orientado a objetos.
Utilizar la programación orientada a objetos sin un buen diseño previo es el camino adecuado para que cualquier proyecto acabe en un desastre.
En mi ejemplo el diseño es muy sencillo. Tenemos una clase llamada Persona, que posee dos propiedades ocultas llamadas nombre y apellidos.
De esta clase hereda la clase Profesor, que añade la propiedad cargo. Y también existe la clase Estudiante, que añade la propiedad curso.
Pasemos a ver el ejemplo.
Aquí en el editor muestro en paralelo los dos ficheros que he realizado. A la izquierda tenemos el ejemplo realizado con arrays, con el estilo procedural, es decir, con funciones sueltas, el ejemplo que mostré en el vídeo anterior. Y a la derecha tenemos el ejemplo realizado con orientación a objetos, es decir, con clases y con objetos.
Lo he puesto así en paralelo para comparar el código en una opción y en la otra, procedural a la izquierda y en orientado a objetos a la derecha.
Aquí tenemos otra vez la función e() que usaba en el ejemplo anterior.
En primer lugar tengo definida la clase Persona. La clase Persona tiene el constructor, tiene el destructor que no hace nada, pero lo he puesto porque ahora vamos a ver una traza de ejecución de los constructores y destructores.
Fíjate que en la función constructor y en la función destructor llamó a la función e(), esta función que tengo declarada aquí, para simplemente mostrar un mensaje y saber que se ha ejecutado el constructor de la clase Persona o el destructor de la clase Persona.
Lo importante es que la clase Persona tiene un constructor que inicializa el nombre y los apellidos que están declarados como protected.
Protected recuerda que es lo mismo que privado, private, pero permite el acceso desde las clases heredadas, pero desde el exterior de la clase no se puede acceder a estas propiedades. Y luego también tenemos la función toString() que me va a convertir una Persona en una cadena, toString(). Y aquí igual que hacía antes compruebo si tiene nombre y apellidos; si no tiene devolveré desconocido, y si tiene devolveré el nombre y los apellidos.
De la clase Persona hereda la clase profesor como podemos ver aquí. La clase profesor va a ser todo lo que sea la clase Persona más ciertas cosas. En concreto la clase Profesor añade una propiedad más, en este caso privada, llamada cargo. Tenemos el constructor, tenemos el destructor. En el constructor voy a llamar al constructor de la clase base, de la clase padre, es decir el constructor de la clase Persona. Y yo le paso el nombre y los apellidos. Yo aquí no tengo que inicializarlo a mano, digamos, yo se lo puedo pasar al constructor de la clase base y entonces se ejecutará este código. Lo mismo con el destructor, yo en el destructor de la clase Profesor puede invocar el destructor de la clase base, es decir, Persona. En este ejemplo no realiza nada, pero en ejemplos más complejos podría ser necesario invocar al destructor.
Y luego tenemos la función toString(). Fíjate aquí ya aparece una ventaja: yo no tengo que volver a escribir el código necesario para mostrar el nombre y los apellidos puede invocar al método toString() de la clase base y simplemente añadirle aquello que añade la clase profesor, aquello que es particular de la clase Profesor.
Esto mismo he realizado con la clase Estudiante que también hereda de la clase Persona y en este caso le añade la propiedad Curso.
Otra vez tenemos el constructor de la clase Estudiante, que invoca el constructor de la clase base, es decir, Persona y le pasa nombre y apellidos para que se inicialice. Y luego le asigna un valor a su propiedad particular que es curso. Otra vez tenemos el destructor y otra vez tenemos el método toString() que llamará al método toString() de la clase base, de Persona y a lo que devuelve le añade el curso.
Fíjate que tanto la clase Profesor como la clase Estudiante, invocan las dos al método toString() de la clase base Persona.
Bien, una vez visto el código de estas tres clases vamos a ver nuestros datos. Nuestros datos los almaceno en un array. En realidad, podría aquí, si hubiese sido orientación a objetos pura, debería de haber creado otra clase de tipo contenedor o lista para almacenar todos estos objetos que estoy creando. Pero no quería complicar el ejemplo creando una cuarta clase. Pero como digo, se podría haber hecho.
En el array almacenamos nuestros objetos que se crean con new y el nombre de la clase. Aquí tenemos dos objetos de tipo Profesor y tres objetos de tipo Estudiante. Y le paso los parámetros para inicializar cada uno de los objetos.
Fíjate que el código, personalmente yo creo que es más fácil de leer que el código del estilo procedural con el array, y además hay que escribir menos. Vale, antes he tenido que escribir más con las clases, pero luego veremos la ventaja.
Lo primero que voy a hacer es mostrar, con un print_r() voy a mostrar el array y vamos a ver su contenido. Me lo guardo y me voy al navegador y recargo la página y vemos aquí en primer lugar temor la traza de las llamadas a los constructores. Fíjate que aparece por cada objeto dos constructores. Aparece el constructor de la clase Profesor y el constructor de la clase base Persona. Estudiante y llama al constructor de la clase base Persona. Y así se repite para los cinco objetos.
Esto mismo luego se repite al final del código, al final de la página pero con la llamada a los destructores. Se invoca al destructor del objeto Profesor y luego dentro de ese destructor invocamos al destructor de la clase base que siempre es Persona, el destructor de la clase Persona.
Bien, fíjate el array tiene cinco posiciones, de la cero a la cuatro, cinco objetos, en cada posición tenemos un objeto. Aquí nos dice que es un objeto de tipo Profesor y aquí nos dice que es un objeto de tipo Estudiante.
Y cada uno tiene pues sus campos, sus propiedades. El profesor tiene nombre, apellidos y cargo; y el estudiante tiene nombre, apellidos y curso.
Bien, volvamos ahora al código y voy a descomentar este fragmento. Bien, fíjate este fragmento es un bucle foreach que me recorre el array $comunidad para mostrarme cada uno de los objetos. Para mostrar cada objeto, $miembro es un objeto, esta posición del array, simplemente tengo que invocar el método toString() que lo he declarado siempre como público, lo puedo invocar desde fuera de la clase.
Este código de aquí equivale a este bucle que tenía aquí. Fíjate que ya tenemos un ahorro, un ahorro de código, de líneas.
En la orientación objetos yo no me tengo que preocupar por el tipo del objeto. Sí he definido bien mis clases, he hecho un buen diseño, como todas las clases tienen el método toString(), yo lo invoco y el intérprete de PHP sabrá en cada momento qué método toString() tiene que invocar; si tiene que invocar el método toString() de la clase Estudiante o tiene que invocar el método toString() de la clase Profesor.
Yo aquí, no me tengo que preocupar de ello, PHP es el que se preocupa de ello.
Sin embargo en el estilo procedural, en el estilo con arrays, yo me tenía que preocupar de ello yo tenía que comprobar en cada momento
si tenía miembro de tipo Profesor o tenía un miembro de tipo Estudiantes e invocar en cada caso el método, el procedimiento adecuado, porque si no lo hacía así pues se cometía un error o el resultado final no era el esperado.
Vamos a ejecutarlo, este código y veremos que funciona correctamente. Y aquí lo tenemos, aquí se visualiza cada uno de los objetos, de tipo Profesor o de tipo Estudiante.
Y ahora otra ventaja de la orientación a objetos. En la orientación a objetos, otra vez, si he hecho un buen diseño, puedo evitar que se comentan, que se hagan cosas que yo no quiero permitir. Por ejemplo, en mi diseño nombre y apellidos los he definido como protegidos, significa que desde fuera de la clase no se pueden modificar. Por tanto, este bucle no se va a ejecutar correctamente, yo estoy intentando cambiar el nombre, ponerle un nombre vacío a todos mis objetos.
Este código debe de fallar. Sin embargo, esto en el estilo procedural, antes vimos en el otro vídeo que sí que era posible, vimos aquí como era posible a todos los miembros cambiarle el tipo, ponerle “estudiante” o oponerle un curso cinco, quinto que no es posible.
Esto, en orientación a objetos, se puede evitar, se fue impedir que se haga.
Bien, vamos a probarlo y veremos como PHP me tiene que mostrar un mensaje de error.
Vamos a recargarlo y ahí aparece el mensaje de error. El mensaje de error me dice que no se puede acceder a la propiedad protegida nombre.
Bien, para finalizar, pues hemos visto dos ventajas importantes de la orientación a objetos. Sí, hay que escribir quizás al principio un poco más de código, pero nos reporta el beneficio de que podemos, por ejemplo, luego escribir código más sencillo y significativo, más fácil de leer y también podemos controlar situaciones que no se deben de dar en nuestro código.
Ya para finalizar, me gustaría recordarte algunos de los sitios web en los que puedes encontrar más información sobre mí y sobre mi trabajo, y dos formas de contactar conmigo, a través de mi correo electrónico sergio.lujan@ua.es y a través de mi cuenta en Twitter @sergiolujanmora.
Recuerda que este vídeo forma parte del curso “Introducción al desarrollo web” que está disponible en la dirección idesweb.es.
Muchas gracias por tu atención.