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:

  1. Usar POO en PHP

  2. Usar Ficheros en PHP

  3. Usar almacenes de datos con XML y JSON

Referencias

Algún material de referencia muy bueno para este tema:

  1. Los tutoriales de JavaTpoint o W3Schools

  2. 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

  1. Clases y Objetos -> php-oops-concepts

    1. Defino una clase (plantilla) con propiedades y métodos

    2. Se define un nivel de acceso concreto (quien puede acceder a ese miembro de la clase) -> php-oops-access-specifiers)

    3. Creo objetos (instancias) con el operador new

    4. Accedemos a una propiedad o un método con el operador ->

  2. Ver el contenido de un objeto -> function.var-dump

  3. Constantes de Clase (language.oop5.constants)

    1. Son propiedades que todos los objetos de esa clase tienen (usamos php-oops-const-keyword para definirlas)

    2. Permiten definir «librerías» de funciones o «constantes»

  4. Clases Estáticas.

    1. Todos los objetos comparten las mismas propiedades y métodos (declarados como static)

    2. Se usa el operador dos puntos (language.oop5.paamayim-nekudotayim): elementos de una clase (no de la instancia)

  5. Construir una clase (php-oops-constructor)

    1. Declaramos como se construye una clase

    2. Permite inicializar valores o preparar los datos para generar la clase

    3. Usamos __construct() o el nombre de la clase

    4. Y también podrías decidir qué hacer cuando se destruye (vía __destruct())

    5. En PHP 8 se ha simplificado bastante la construcción de clases

Actividad T05-A01. Conceptos básicos POO en PHP

  1. Crea una clase vehículos (vehiculos.inc) con:

    1. Un constructor para crear el objeto

    2. 2 propiedades (matr y edad)

    3. 3 métodos

      1. ver(). Que muestra «El vehículo con matrícula $matr tiene una antigüedad de $edad años»

      2. actualizar_matricula(). Para cambiar el nombre del vehiculo

      3. ver_completo(). Para ver el contenido completo de la instancia

  2. Crea una página web (script sin interactividad) que, usando esta clase:

    1. Cree dos objetos (v1 y v2)

    2. Muestre v1.ver() y v2.ver_completo().

    3. Actualice la matrícula de v2

    4. Muestre la matrícula de v2

5.2. Abstracción, Herencia y Encapsulamiento

  1. Abstracción. PHP permite clases abstractas -> php-oops-abstract-class

    1. Añades abstract en los métodos, que la clase hija debe implementar (cuando extiendes la clase abstracta)

    2. Puedes definir una interfaz (php-oops-interface) si son abstractos todos los métodos que debes implementar

    3. 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

  2. Herencia (php-oops-inheritance)

    1. Una clase puede heredar («extends») propiedades y métodos de otra

    2. Permite una clasificación jerárquica de los datos

    3. PHP permite herencia simple (sólo de una clase) aunque puede heredar de varias usando interfaces

    4. Se puede limitar la herencia a un método, es decir, que no se pueda implementar por un descendiente (php-oops-final-keyword)

  3. Encapsulación (php-oops-encapsulation):

    1. Busco proteger los datos de la instancia

    2. Usando sólo métodos para gestionarlos (operaciones CRUD)

    3. Lo uso cuando me interesa esconder ciertas propiedades o funcionalidad

  4. Sobrecarga (de métodos). Un método hijo sobreescribe el método parent (parent)

  5. Implementación del modelo OO:

    1. Ideal incluir las clases en un archivo (o más si te interesa) …

    2. … que luego se incluyen (function.include-once) en las páginas que te interese

    3. La ejecución se suele plantear en el archivo principal (o controlador si usas MVC)

  6. El diseño del modelo de clases (modelo de datos) suele estar en un diagrama UML ( Repasar )

    1. Creas las clases

    2. Creas las propiedades, con su tipo de acceso

    3. 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:

../_images/ejemplo_uml_1.png

5.3. Más funcionalidad en PHP

  1. Hay varias librerías de clases, las incluidas en PHP son:

    1. Interfaces y Clases Predefinidas -> reserved.interfaces

    2. La Biblioteca Standard PHP Library -> book.spl

  2. Librerías SPL

    1. Es una extensión pero ya incluida con PHP

    2. Define una colección de interfaces y clases que pueden servir para resolver diferentes problemas. Por ejemplo para:

      1. Gestionar estructuras de datos complejas

      2. Usar diferentes tipos de iteradores

      3. Usar interfaces

      4. Usar funciones útiles para programación OO

      5. Clases para gestionar archivos

    3. Permite el uso complejo de POO en PHP

  3. Y, además, puedes aumentar la funcionalidad de instalación php:

    1. Con extensiones PHP: extensions.alphabetical. Necesitas comprobar que esté instalada, a veces son librerías de funciones, a veces de clases.

    2. Usando gestores de paquetes (p.ej con Composer o PEAR )

  4. En la práctica, usarás o funciones o clases. Dos ejemplos de uso de POO:

    1. Interfaz Countable class.countable

      1. Añade el método count() a la clase que definas

    2. Interfaz Iterator class.iterator

      1. Hereda de la clase Transversable que permite recorrer el objeto con un foreach

      2. Permite recorrer los elementos de un objeto

      3. Definiendo una serie de métodos (definidos en la clase)

Actividad T05-A03. Creación de Clases en POO

  1. Cambia el diseño de la clase Estudiante y Profesor implementando la interfaz Countable

  2. Crea una clase Personas que permita recorrer un array de objetos persona. Para ello necesitas:

    1. Crear la clase con propiedades apuntador y array de personas que …

    2. implementa la interfaz Iterator

    3. e implementas los métodos que define la interfaz

5.4. Uso de Ficheros (Recursos)

  1. En PHP los archivos (ficheros) son un caso particular de recurso:

    1. Un recurso puede ser de diferentes tipos : wrappers

    2. Se considera un flujo de datos (stream: intro.stream):

      1. Se abre el flujo (conjunto de datos que se va utilizando)

      2. Se va usando

      3. Se cierra

    3. Para cada tipo de flujo de datos se puede adaptar el comportamiento (contexto) usando las misma funcionalidad

  2. Hay un montón de funciones para gestionar archivos (y recursos) en PHP ref.filesystem. Por ejemplo:

    1. Para ver información sobre el archivo

    2. Para ver información del sistema de archivos (rutas, directorios, etc)

    3. Para operar el archivo (abrir, cerrar, leer, escribir, moverse, etc)

    4. Para operar el archivo dentro del sistema de archivos (copiar, mover, etc)

  3. Un tutorial sencillo de manejo ( Manejo de Archivos en PHP )

    1. Abrir, leer, escribir y cerrar un archivo (en bloques, en líneas o completo)

    2. Recorres el archivo (en el flujo de datos). Interesante en algunos casos (no tanto para desarrollo web)

    3. 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)

  4. Y además, puedes usar clases e interfaces, por ejemplo:

    1. Información de un archivo: book.fileinfo

    2. Trabajo con Directorios: book.dir

    3. Y hasta usando la librería SPL:

      1. Información sobre un archivo individual class.splfileinfo

      2. Manejar el Fichero con una clase específica: class.splfileobject (puede ser un fichero temporal con class.spltempfileobject

  5. Sin embargo, en la práctica, y en el contexto de desarrollo web, el uso de ficheros suele ser más sencillo:

    1. Revisar que existe el fichero function.file-exists

    2. Usar las funciones

      1. function.file-get-contents (leer todo el contenido de un fichero)

      2. o function.file-put-contents (escribir todo el contenido)

Actividad T05-A04. Manejo de archivos en PHP

  1. Muestra el nombre y ruta de un archivo

  2. Crea una función que detecte si un archivo existe

  3. Carga un archivo de texto en una variable

  4. Escribe los elementos de un array en un archivo, línea a línea. Es decir, cada elemento en una línea

  5. Lee los elementos de un array

  6. Lee la primera línea de un archivo csv de ejemplo, y crea un array con cada elemento (que va separado por comas)

  7. Tienes un directorio con varias imágenes. Crear un array con los nombre de archivos que terminen en .jpg

  8. Crea una página web sencilla que cargue las imágenes. ¿Qué ocurre si añades o borras una imagen?

  9. Añade a esa web, le fecha de creación de la imagen

  10. 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 :

    1. Cargue en la variable titulo el contenido de H1 (sólo el texto)

    2. Busca el contenido de los elementos span que el atributo class a «caption-text»

    3. Busca el valor del atributo href de los elementos a de la web externa

5.5. Almacenar Objetos (Serializar)

  1. Serializar implica convertir un objeto en texto (String) y por eso …

  2. … lo puedo gestionar (asignar a una variable o guardarlo en un archivo)

  3. … y después, a partir de un objeto serializado, recuperarlo.

  4. Es una forma de almacenar objetos (y recuperarlos)

    1. Generas un objeto que se puede almacenar (vía function.serialize)

    2. Lo guardas en un archivo (por ejemplo) y luego

    3. Lo podrías leer y «deserializar» vía function.unserialize

    4. Atención al intercambiar objetos serializados (sólo desde orígenes fiables)

  5. Esta función, permite tener almacenes de datos sencillos

    1. Tienes un almacén de objetos

    2. Los almacenas en memoria

    3. Lo guardas en un archivo

    4. 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

  1. Guardar en un archivo (almacen.txt) tres objetos (instancias de) la clase «Persona» diseñadas en tu librería de clases «mis_clases.inc».

  2. Puedes usar dos estrategias:

    1. Guardas un objeto por línea. Es decir, cada persona la tendrás guardada en una línea del archivo

    2. Creas una colección de personas (array de objetos) y la guardas completa

  3. Y, aunque lo veremos al final del tema, podrías crear una clase Almacen que permita operarlo:

    1. Leer una persona concreta

    2. Actualizar los datos de una personas concreta

    3. Añadir una persona

    4. Eliminar una persona

5.6. Usando el DOM API en PHP

  1. PHP tiene varias alternativas para gestionar el DOM (sea XML o HTML) y que te permite:

    1. Leer archivos XML

    2. Analizar páginas HTML

    3. Editar el DOM y reescribirlo

  2. Una opción sencilla es SimpleXML (book.simplexml) pero vamos a utilizar la más completa: book.dom

    1. Permite: construir, modificar, validar, consultar y transformar documentos XML

    2. Carga el XML en Memoria como una colección de objetos

    3. Tanto elementos como atributos serán objetos (nodos)

    4. Hay un objeto raíz (master). Es un nodo (DOMNode) que contiene nodos

  3. Procedimiento habitual para cargar el XML en memoria:

    1. Crear el objeto (DOMDocument class.domdocument ) y cargarlo, por ejemplo, desde un archivo (domdocument.load)

    2. (opcional) Comprobar y Validar el documento (vía propiedad doctype y/o método domdocument.validate). Acepta validaciones más complejas

    3. Obtener el nodo que nos interesa, a través de:

      1. Un DOMElement (class.domelement) que obtener usando domdocument.getelementbyid

      2. O una colección de nodos (class.domnodelist) usando domdocument.getelementsbytagname

    4. El documento es un árbol de nodos jerárquicamente relacionados.

      1. Un nodo es representado por DOMNode (class.domnode)

      2. Me permite encadenar métodos porque un nodo a su vez puede tener nodos descendientes

    5. El valor de un nodo se puede consultar de forma sencilla usando la propiedad nodeValue o textContent

  4. Se pueden realizar consultas de nodos usando XPATH class.domxpath

    1. Se define la cadena xpath y se consulta desde el objeto método query

    2. Tienes una colección de elemenos (nodos) con los que operar

  5. 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

  1. Uso de JSON

    1. Una cosa es el archivo (serializacion del objeto) y otra el objeto en sí

    2. Simplifica enormemente el intercambio de datos porque define un estándar (RFC 7159)

    3. El coste es la pérdida de validación e integridad (que hay que gestionar a nivel de la aplicación)

    4. Tipo Mime: application/json (RFC 4627)

    5. Su gran ventaja, además del estándar, es que es muy ligero.

  2. PHP tiene una extensión específica para gestionar archivos json (book.json):

    1. Serializar: function.json-encode

    2. Recuperar: function.json-decode

    3. Permite también personalizar el comportamiento y controlar los errores

  3. Programación OO con JSON:

    1. Al ser objetos, se puede usar una equivalencia entre el Objeto PHP y el Objeto JSON

    2. Significa usar JSON como cadena de texto al serializar el objeto

    3. 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:

  1. El listado completo de usuarios en el almacén

  2. 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

  1. Se puede implementar el modelo de datos de la aplicación, sin utilizar un sistema de gestión de bases de datos (SGBD):

    1. Modelo de datos en clases y almacenamos en archivo de texto serializando los objetos

    2. Modelo de datos usando JSON

    3. Modelo de datos usando XML

  2. Soporte de los datos:

    1. JSON y XML permite gestionar almacenes de datos sencillos, sin usar un sistema externo más complejo

      1. Usa JSON para almacenes con una estructura sencilla y que no necesite un control de validación muy fuerte

      2. Usa XML para almacenes de datos con estructura más compleja o con un control más estricto de los datos

      3. El uso de JSON es mucho más rápido y ligero que con XML

    2. El uso de la serialización de objetos puede ser muy útil si el modelo de datos tiene cierta complejidad.

  3. Además de tener un soporte para el almacén, necesitas implementar las operaciones CRUD :

    1. Create. Añadir

    2. Read. Consultar

    3. Update. Actualizar

    4. Delete. Borrar

  4. Implementación de un almacén de datos usando programación OO y el API DOM con XML

    1. Defines el archivo donde guardarás los datos (por ejemplo usuarios.xml)

    2. Puedes añadir las instrucciones de validación (doctype o Xschema) si necesitas validarlo

    3. Creas una clase para el manejo del almacén (todo el almacén completo se carga en memoria)

    4. Implementas los métodos más habituales:

      1. Constructor: crear el objeto desde el archivo (la misma clase, serviría para diferentes almacenes)

      2. Destructor: al tener el objeto en memoria, es importante gestionar qué hacer al destruirlo (por ejemplo guardarlo)

      3. Implementar las diferentes operaciones: añadir, leer, consultar, actualizar

      4. Implemantar las operaciones específicas que te interesen, por ejemplo hacer listados o filtrar datos

    5. 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:

  1. Usarás un formulario para añadir datos que además …

  2. de los campos del usuario (de la sesión anterior), permitirá decir en qué almacén guardar el usuario (XML o JSON)

  3. Implementarás las operaciones CRUD

  4. Será una aplicación con toda la programación en el servidor, es decir, sin usar JS