Qué se construye
El proyecto de la unidad es un CRUD completo en PHP, con HTML y CSS, sobre una tabla propia. Es el trabajo que integra todo lo que se vio en la materia: el diseño de la tabla —los tipos, la clave primaria, las restricciones—, la pantalla que pide los datos, el programa que los valida y los guarda, y las cuatro operaciones funcionando sobre el mismo sistema.
«Completo» quiere decir las cuatro: se pueden cargar datos, verlos en un listado, corregir lo que se cargó mal y dar de baja lo que ya no va. Un proyecto con tres de las cuatro no está aprobado, y no por una cuestión formal: como se vio en la página de CRUD, un sistema al que le falta una operación obliga a llevar la cuenta por otro lado, y eso lo vuelve inservible a la larga. Además, el acceso se protege con un login: solo quien tiene sesión llega al listado. La explicación completa, archivo por archivo, está en su propia página: Login y sesiones.
El tema de la tabla se elige. Puede ser la biblioteca que se usó de ejemplo en toda la unidad, o cualquiera que tenga sentido: socios de un club, alumnos de un curso, productos de un kiosco, turnos de un consultorio, libros, instrumentos, mascotas. Lo que importa es que los datos tengan al menos un campo obligatorio y único —un documento, un código, una patente— porque en algún momento el sistema va a tener que rechazar un duplicado y hay que poder mostrarlo bien.
El repositorio
El ejemplo del proyecto está publicado en GitHub. Son varios repositorios, y el del CRUD está fijado en la portada del perfil, así que se encuentra apenas se abre:
En el repositorio está el proyecto listo para ejecutar: el código PHP, el HTML, el CSS y el script .sql con la creación de las tablas y algunos datos de ejemplo para que el sistema no arranque vacío. Se lo puede descargar, copiar a la carpeta del servidor y abrir en el navegador.
Los archivos del proyecto
Un CRUD se organiza en varios archivos, uno por responsabilidad. No es una regla obligatoria, pero sí la forma más clara de armarlo:
| Archivo | Qué hace |
|---|---|
conexion.php | Abre la conexión con la base. Lo incluyen todos los demás. |
listado.php | La R. El listado, con el buscador y los botones de cada fila. Es la pantalla principal. |
alta.php | La C. Muestra el formulario vacío y, cuando se envía, guarda el dato. |
editar.php | Muestra el formulario de edición con los datos actuales de la fila. |
modificar.php | La U. Procesa los cambios que llegaron del formulario de edición. |
confirmar-baja.php | La pantalla que muestra qué se va a dar de baja y pide confirmación. |
baja.php | La D. Ejecuta la baja, después de la confirmación. |
estilos.css | El CSS de todo el sistema. |
biblioteca.sql | El CREATE TABLE y los datos de ejemplo, para importar desde el gestor. |
La existencia de conexion.php merece una explicación, porque es una decisión y no una casualidad. La conexión la necesitan todos los archivos, y podría estar escrita dentro de cada uno. Está en un solo lugar por la misma razón por la que el CSS va en una hoja externa y no dentro del <head> de cada página: para cambiarla una sola vez. El día que la base cambie de servidor o de contraseña —o que se pase de MySQL a SQLite— hay un archivo que tocar, no nueve.
Los dos archivos de la baja, confirmar-baja.php y baja.php, también son una decisión. Podrían ser uno solo, pero separarlos hace imposible la baja accidental: para llegar al baja.php hay que haber pasado sí o sí por la pantalla de confirmación, porque es la única que tiene el botón que lo llama.
El recorrido de una operación
Para cerrar, el recorrido completo de una modificación, que es el que usa más pasos. Vale seguirlo entero, porque en él aparecen todas las piezas de la unidad:
| # | Qué pasa | Método | Qué se usa |
|---|---|---|---|
| 1 | El usuario abre el listado y busca el socio. | GET |
SELECT con WHERE y ORDER BY |
| 2 | Aprieta «Editar» en esa fila. El enlace lleva el id. |
GET |
Un enlace editar.php?id=47 |
| 3 | El programa busca esa fila y arma el formulario con los datos. | GET |
SELECT por id + htmlspecialchars() |
| 4 | El usuario cambia lo que necesita y envía. | POST |
Un <form> con el id en un campo oculto |
| 5 | El programa valida otra vez lo que llegó. | — | Las mismas reglas que el formulario, en el servidor |
| 6 | Arma la consulta con marcadores y la ejecuta. | — | UPDATE ... WHERE id = :id con prepare() |
| 7 | Comprueba que haya cambiado algo y redirige. | — | rowCount() + header('Location: …') |
| 8 | El listado se vuelve a armar, ya con el dato corregido. | GET |
El mismo SELECT del paso 1 |
Fijate en el paso 7: la redirección vuelve al listado, que se arma consultando de nuevo la base. Eso es lo que cierra el circuito. El usuario no ve un cartel que le dice «se guardó»: ve el dato ya cambiado en la lista. Es más convincente que cualquier mensaje, y de paso evita el problema del reenvío que duplicaba datos. Un CRUD bien hecho siempre termina mostrando la realidad de la base, no un aviso sobre ella.
Qué tiene que tener
La lista de comprobación del proyecto, armada con todo lo que se vio en la unidad. Si algo de esto falta, el sistema funciona pero no está terminado:
| Tiene que tener | Porque si no… |
|---|---|
| Las cuatro operaciones | El sistema está incompleto y hay que llevar parte del trabajo por afuera. |
| Una tabla con clave primaria y al menos una restricción que se haga valer | No hay nada que impida los datos duplicados ni las referencias al vacío. |
| Validación en el servidor | La del navegador se saltea con dos clics, y entra cualquier cosa. |
| Consultas preparadas en todo lo que lleve valores | Aplicar la técnica explicada en Inyección SQL. |
htmlspecialchars() en todo lo que se muestra |
Un dato cargado con símbolos de HTML rompe la página o ejecuta código. |
| Confirmación antes de la baja | Un clic apurado destruye información sin vuelta atrás. |
| Baja lógica —o una razón para la física— | Se pierde el historial y no se puede deshacer un error. |
| Mensajes claros cuando algo falla | El usuario ve un error técnico que no entiende y no sabe qué corregir. |
| Un listado ordenado y con al menos un filtro | Con más de cincuenta filas, encontrar algo se vuelve imposible. |
| El CSS, para que se pueda usar sin explicaciones | Un sistema que hay que enseñar a usar ya está mal diseñado. |
Ninguno de esos diez puntos es un requisito formal: cada uno responde a un problema concreto que aparece en un sistema real. Los cinco primeros son de corrección y seguridad; los otros cinco, de que el sistema se pueda usar sin lastimarse. Un CRUD que los cumple no es un ejercicio resuelto: es una aplicación que se le puede dar a alguien para que trabaje con ella.
Resumen
- El proyecto es un CRUD completo en PHP, con HTML y CSS, sobre una tabla propia.
- Completo significa las cuatro operaciones: cargar, listar, modificar y dar de baja.
- El ejemplo está publicado en GitHub, fijado en la portada del perfil:
github.com/MauroBobyk. - El repositorio trae el código, el CSS y el script
.sqlcon las tablas y datos de ejemplo. - El ejemplo es para inspeccionar cómo funciona, no para copiar y entregar.
- El proyecto se organiza en un archivo por responsabilidad, y la conexión va en uno solo.
- La conexión se centraliza por la misma razón que el CSS va en una hoja externa: para cambiarla una sola vez.
- Separar la confirmación de la baja hace imposible el borrado accidental.
- El circuito termina volviendo al listado, que se arma consultando de nuevo la base: el usuario ve el dato cambiado, no un aviso.
- La lista de comprobación son diez puntos que responden a problemas reales, no a requisitos formales.