5. Programación Orientada a Objetos con PHP¶
Siguiendo con programación en PHP, vamos a ver cómo usar la programación orientada a objetos (POO) en PHP y también el manejo de ficheros. En este tema aprenderás a:
Usar POO en PHP
Usar Ficheros en PHP
Usar almacenes de datos con XML y JSON
Referencias
Algún material de referencia muy bueno para este tema:
Los tutoriales de JavaTpoint o W3Schools
El tema específico del curso de Aitor Medrano
Está organizado en 8 talleres de unas 3 sesiones de clase. En total unas 24 sesiones de clase más tu trabajo en casa.
La dedicación depende del conocimiento previo, motivación y capacidad de aprendizaje del estudiante para esa sesión en concreto.
5.1. Clases y Objetos¶
Clases y Objetos -> php-oops-concepts
Defino una clase (plantilla) con propiedades y métodos
Se define un nivel de acceso concreto (quien puede acceder a ese miembro de la clase) -> php-oops-access-specifiers)
Creo objetos (instancias) con el operador new
Accedemos a una propiedad o un método con el operador ->
Ver el contenido de un objeto -> function.var-dump
Constantes de Clase (language.oop5.constants)
Son propiedades que todos los objetos de esa clase tienen (usamos php-oops-const-keyword para definirlas)
Permiten definir «librerías» de funciones o «constantes»
Clases Estáticas.
Todos los objetos comparten las mismas propiedades y métodos (declarados como static)
Se usa el operador dos puntos (language.oop5.paamayim-nekudotayim): elementos de una clase (no de la instancia)
Construir una clase (php-oops-constructor)
Declaramos como se construye una clase
Permite inicializar valores o preparar los datos para generar la clase
Usamos __construct() o el nombre de la clase
Y también podrías decidir qué hacer cuando se destruye (vía __destruct())
En PHP 8 se ha simplificado bastante la construcción de clases
Actividad T05-A01. Conceptos básicos POO en PHP
Crea una clase vehículos (vehiculos.inc) con:
Un constructor para crear el objeto
2 propiedades (matr y edad)
3 métodos
ver(). Que muestra «El vehículo con matrícula $matr tiene una antigüedad de $edad años»
actualizar_matricula(). Para cambiar el nombre del vehiculo
ver_completo(). Para ver el contenido completo de la instancia
Crea una página web (script sin interactividad) que, usando esta clase:
Cree dos objetos (v1 y v2)
Muestre v1.ver() y v2.ver_completo().
Actualice la matrícula de v2
Muestre la matrícula de v2
5.2. Abstracción, Herencia y Encapsulamiento¶
Abstracción. PHP permite clases abstractas -> php-oops-abstract-class
Añades abstract en los métodos, que la clase hija debe implementar (cuando extiendes la clase abstracta)
Puedes definir una interfaz (php-oops-interface) si son abstractos todos los métodos que debes implementar
Te puede convenir definir clases abstractas (algo sin definir y con propiedades) o interfaces (todo por definir) -> php-oops-difference-between-abstract-class-and-interface
Herencia (php-oops-inheritance)
Una clase puede heredar («extends») propiedades y métodos de otra
Permite una clasificación jerárquica de los datos
PHP permite herencia simple (sólo de una clase) aunque puede heredar de varias usando interfaces
Se puede limitar la herencia a un método, es decir, que no se pueda implementar por un descendiente (php-oops-final-keyword)
Encapsulación (php-oops-encapsulation):
Busco proteger los datos de la instancia
Usando sólo métodos para gestionarlos (operaciones CRUD)
Lo uso cuando me interesa esconder ciertas propiedades o funcionalidad
Sobrecarga (de métodos). Un método hijo sobreescribe el método parent (parent)
Implementación del modelo OO:
Ideal incluir las clases en un archivo (o más si te interesa) …
… que luego se incluyen (function.include-once) en las páginas que te interese
La ejecución se suele plantear en el archivo principal (o controlador si usas MVC)
El diseño del modelo de clases (modelo de datos) suele estar en un diagrama UML ( Repasar )
Creas las clases
Creas las propiedades, con su tipo de acceso
Creas los métodos
Actividad T05-A02. Creación de Clases en POO
Lo recomendado es usar un archivo por cada clase y usar la extensión .inc para distinguirlo de la programación en sí. Para simplificar, podemos usar un sólo archivo con todas las clases.
Implementa el archivo «mis_clases.inc» que contenga las clases descritas en el siguiente diseño POO:
5.3. Más funcionalidad en PHP¶
Hay varias librerías de clases, las incluidas en PHP son:
Interfaces y Clases Predefinidas -> reserved.interfaces
La Biblioteca Standard PHP Library -> book.spl
Librerías SPL
Es una extensión pero ya incluida con PHP
Define una colección de interfaces y clases que pueden servir para resolver diferentes problemas. Por ejemplo para:
Gestionar estructuras de datos complejas
Usar diferentes tipos de iteradores
Usar interfaces
Usar funciones útiles para programación OO
Clases para gestionar archivos
Permite el uso complejo de POO en PHP
Y, además, puedes aumentar la funcionalidad de instalación php:
Con extensiones PHP: extensions.alphabetical. Necesitas comprobar que esté instalada, a veces son librerías de funciones, a veces de clases.
En la práctica, usarás o funciones o clases. Dos ejemplos de uso de POO:
Interfaz Countable class.countable
Añade el método count() a la clase que definas
Interfaz Iterator class.iterator
Hereda de la clase Transversable que permite recorrer el objeto con un foreach
Permite recorrer los elementos de un objeto
Definiendo una serie de métodos (definidos en la clase)
Actividad T05-A03. Creación de Clases en POO
Cambia el diseño de la clase Estudiante y Profesor implementando la interfaz Countable
Crea una clase Personas que permita recorrer un array de objetos persona. Para ello necesitas:
Crear la clase con propiedades apuntador y array de personas que …
implementa la interfaz Iterator
e implementas los métodos que define la interfaz
5.4. Uso de Ficheros (Recursos)¶
En PHP los archivos (ficheros) son un caso particular de recurso:
Un recurso puede ser de diferentes tipos : wrappers
Se considera un flujo de datos (stream: intro.stream):
Se abre el flujo (conjunto de datos que se va utilizando)
Se va usando
Se cierra
Para cada tipo de flujo de datos se puede adaptar el comportamiento (contexto) usando las misma funcionalidad
Hay un montón de funciones para gestionar archivos (y recursos) en PHP ref.filesystem. Por ejemplo:
Para ver información sobre el archivo
Para ver información del sistema de archivos (rutas, directorios, etc)
Para operar el archivo (abrir, cerrar, leer, escribir, moverse, etc)
Para operar el archivo dentro del sistema de archivos (copiar, mover, etc)
Un tutorial sencillo de manejo ( Manejo de Archivos en PHP )
Abrir, leer, escribir y cerrar un archivo (en bloques, en líneas o completo)
Recorres el archivo (en el flujo de datos). Interesante en algunos casos (no tanto para desarrollo web)
Puedes consultar información de un archivo completo (function.stat) o por ejemplo ver los archivos que cumplen con un patrón de búsqueda (function.glob)
Y además, puedes usar clases e interfaces, por ejemplo:
Información de un archivo: book.fileinfo
Trabajo con Directorios: book.dir
Y hasta usando la librería SPL:
Información sobre un archivo individual class.splfileinfo
Manejar el Fichero con una clase específica: class.splfileobject (puede ser un fichero temporal con class.spltempfileobject
Sin embargo, en la práctica, y en el contexto de desarrollo web, el uso de ficheros suele ser más sencillo:
Revisar que existe el fichero function.file-exists
Usar las funciones
function.file-get-contents (leer todo el contenido de un fichero)
o function.file-put-contents (escribir todo el contenido)
Actividad T05-A04. Manejo de archivos en PHP
Muestra el nombre y ruta de un archivo
Crea una función que detecte si un archivo existe
Carga un archivo de texto en una variable
Escribe los elementos de un array en un archivo, línea a línea. Es decir, cada elemento en una línea
Lee los elementos de un array
Lee la primera línea de un archivo csv de ejemplo, y crea un array con cada elemento (que va separado por comas)
Tienes un directorio con varias imágenes. Crear un array con los nombre de archivos que terminen en .jpg
Crea una página web sencilla que cargue las imágenes. ¿Qué ocurre si añades o borras una imagen?
Añade a esa web, le fecha de creación de la imagen
Carga una página web externa (por ejemplo
https://www.apuntesinformaticafp.com/
) como si fuera un recurso (archivo) y que puedas filtrar el texto para :Cargue en la variable titulo el contenido de H1 (sólo el texto)
Busca el contenido de los elementos span que el atributo class a «caption-text»
Busca el valor del atributo href de los elementos a de la web externa
5.5. Almacenar Objetos (Serializar)¶
Serializar implica convertir un objeto en texto (String) y por eso …
… lo puedo gestionar (asignar a una variable o guardarlo en un archivo)
… y después, a partir de un objeto serializado, recuperarlo.
Es una forma de almacenar objetos (y recuperarlos)
Generas un objeto que se puede almacenar (vía function.serialize)
Lo guardas en un archivo (por ejemplo) y luego
Lo podrías leer y «deserializar» vía function.unserialize
Atención al intercambiar objetos serializados (sólo desde orígenes fiables)
Esta función, permite tener almacenes de datos sencillos
Tienes un almacén de objetos
Los almacenas en memoria
Lo guardas en un archivo
En algunos casos, tendrás que leer/escribir continuamente al sistema de almacenamiento (ojo a la concurrencia)
Actividad T05-A05. Crear un almacén de datos con objetos serializados
Guardar en un archivo (almacen.txt) tres objetos (instancias de) la clase «Persona» diseñadas en tu librería de clases «mis_clases.inc».
Puedes usar dos estrategias:
Guardas un objeto por línea. Es decir, cada persona la tendrás guardada en una línea del archivo
Creas una colección de personas (array de objetos) y la guardas completa
Y, aunque lo veremos al final del tema, podrías crear una clase Almacen que permita operarlo:
Leer una persona concreta
Actualizar los datos de una personas concreta
Añadir una persona
Eliminar una persona
5.6. Usando el DOM API en PHP¶
PHP tiene varias alternativas para gestionar el DOM (sea XML o HTML) y que te permite:
Leer archivos XML
Analizar páginas HTML
Editar el DOM y reescribirlo
Una opción sencilla es SimpleXML (book.simplexml) pero vamos a utilizar la más completa: book.dom
Permite: construir, modificar, validar, consultar y transformar documentos XML
Carga el XML en Memoria como una colección de objetos
Tanto elementos como atributos serán objetos (nodos)
Hay un objeto raíz (master). Es un nodo (DOMNode) que contiene nodos
Procedimiento habitual para cargar el XML en memoria:
Crear el objeto (DOMDocument class.domdocument ) y cargarlo, por ejemplo, desde un archivo (domdocument.load)
(opcional) Comprobar y Validar el documento (vía propiedad doctype y/o método domdocument.validate). Acepta validaciones más complejas
Obtener el nodo que nos interesa, a través de:
Un DOMElement (class.domelement) que obtener usando domdocument.getelementbyid
O una colección de nodos (class.domnodelist) usando domdocument.getelementsbytagname
El documento es un árbol de nodos jerárquicamente relacionados.
Un nodo es representado por DOMNode (class.domnode)
Me permite encadenar métodos porque un nodo a su vez puede tener nodos descendientes
El valor de un nodo se puede consultar de forma sencilla usando la propiedad
nodeValue
otextContent
Se pueden realizar consultas de nodos usando XPATH class.domxpath
Se define la cadena xpath y se consulta desde el objeto
método query
Tienes una colección de elemenos (nodos) con los que operar
Un resumen sencillo (en inglés):
Actividad T05-A06. Consulta un archivo XML
Consulta un archivo XML de ejemplo usando el API DOM de PHP
5.7. Uso de archivos JSON¶
Uso de JSON
Una cosa es el archivo (serializacion del objeto) y otra el objeto en sí
Simplifica enormemente el intercambio de datos porque define un estándar (RFC 7159)
El coste es la pérdida de validación e integridad (que hay que gestionar a nivel de la aplicación)
Tipo Mime: application/json (RFC 4627)
Su gran ventaja, además del estándar, es que es muy ligero.
PHP tiene una extensión específica para gestionar archivos json (book.json):
Serializar: function.json-encode
Recuperar: function.json-decode
Permite también personalizar el comportamiento y controlar los errores
Programación OO con JSON:
Al ser objetos, se puede usar una equivalencia entre el Objeto PHP y el Objeto JSON
Significa usar JSON como cadena de texto al serializar el objeto
Puede ser útil si la aplicación tiene un fuerte componente de objetos.
Actividad T05-A07. Usando JSON como almacén de datos
Crea una aplicación web que gestione usuarios (con dni, nombre e email) utilizando el almacén de datos «usuarios.json». Permitirá ver:
El listado completo de usuarios en el almacén
Los datos de un usuario (con dni concreto)
Puedes utilizar maquetación con rejilla (grid), que quizá es la más sencilla para mostrar los datos.
5.8. Almacenar Datos en archivos¶
Se puede implementar el modelo de datos de la aplicación, sin utilizar un sistema de gestión de bases de datos (SGBD):
Modelo de datos en clases y almacenamos en archivo de texto serializando los objetos
Modelo de datos usando JSON
Modelo de datos usando XML
Soporte de los datos:
JSON y XML permite gestionar almacenes de datos sencillos, sin usar un sistema externo más complejo
Usa JSON para almacenes con una estructura sencilla y que no necesite un control de validación muy fuerte
Usa XML para almacenes de datos con estructura más compleja o con un control más estricto de los datos
El uso de JSON es mucho más rápido y ligero que con XML
El uso de la serialización de objetos puede ser muy útil si el modelo de datos tiene cierta complejidad.
Además de tener un soporte para el almacén, necesitas implementar las operaciones CRUD :
Create. Añadir
Read. Consultar
Update. Actualizar
Delete. Borrar
Implementación de un almacén de datos usando programación OO y el API DOM con XML
Defines el archivo donde guardarás los datos (por ejemplo usuarios.xml)
Puedes añadir las instrucciones de validación (doctype o Xschema) si necesitas validarlo
Creas una clase para el manejo del almacén (todo el almacén completo se carga en memoria)
Implementas los métodos más habituales:
Constructor: crear el objeto desde el archivo (la misma clase, serviría para diferentes almacenes)
Destructor: al tener el objeto en memoria, es importante gestionar qué hacer al destruirlo (por ejemplo guardarlo)
Implementar las diferentes operaciones: añadir, leer, consultar, actualizar
Implemantar las operaciones específicas que te interesen, por ejemplo hacer listados o filtrar datos
Repasa el uso de Xpath ( XPath Tutorial ), que permite seleccionar nodos en almacenes complejos
Actividad T05-A08. Gestionar usuarios con un almacén de datos en archivo/s
Desarrolla una aplicación web que permita gestionar los usuarios en un almacén de datos:
Usarás un formulario para añadir datos que además …
de los campos del usuario (de la sesión anterior), permitirá decir en qué almacén guardar el usuario (XML o JSON)
Implementarás las operaciones CRUD
Será una aplicación con toda la programación en el servidor, es decir, sin usar JS