En este tutorial vamos a ver cómo crear una aplicación CRUD con PHP y MySQL. Crearemos tanto el backend como el frontend de la aplicación. No usaremos ningún framework, sino las extensiones y los métodos nativos de PHP. La aplicación soportará la lectura, la escritura, la actualización y el borrado de registros en la base de datos. Para las vistas usaremos únicamente HTML y CSS.
Este es un tutorial de introducción especialmente creado para aquellas personas que se estén iniciando con el desarrollo de aplicaciones con PHP. Por ello, no crearemos un gestor de rutas ni usaremos composer. Tampoco dividiremos la aplicación en modelos, vistas y controladores tal y como dicta el patrón de diseño MVC, siendo algo que dejaremos para otro tutorial.
Contenidos
- 1 Introducción
- 2 Configuración del Host
- 3 Creación de la plantilla HTML
- 4 Configuración de la base de datos
- 5 Creación de la aplicación CRUD
- 6 Protección CSRF
- 7 Conclusión
Introducción
Vamos a crear una sencilla aplicación que permita gestionar los datos de los alumnos de un colegio. Necesitamos agregar las funcionalidades que nos permitan crear un alumno, mostrar una lista de alumnos, editar los datos de un alumno y eliminar un alumno.
Intentaremos usar las funcionalidades más recientes posibles de PHP y tomaremos ciertas consideraciones de seguridad, aun que este tutorial no deja de ser de aprendizaje. De todos modos, antes de continuar, es recomendable que tengas unos conocimientos básicos de HTML y de PHP:
- Si nunca has usado HTML, consulta primero la guía definitiva de HTML para aprender los conceptos más importantes.
- Si nunca has usado PHP, consulta la guía definitiva de PHP, en donde además de aprender tus primeros pasos, verás cómo instalar y configurar PHP en tu sistema operativo.
- Para gestionar las bases de datos MySQL usaremos phpMyAdmin, que es una herramienta que se instala con paquetes como Wamp, XAMPP o MAMP, aunque también puedes usar herramientas como Sequel Pro. De todos modos, también veremos cómo crear todas las consultas MySQL manualmente.
Lo primero que veremos en este tutorial será cómo conectarnos a una base de datos MySQL con PHP usando PDO (PHP Data Objects). Seguidamente crearemos un script que cree tanto la base de datos como las tablas de la misma. Luego crearemos un formulario HTML que envíe datos al servidor. En el servidor, usaremos sentencias preparadas para insertar registros en la base da datos. Finalmente obtendremos los datos de la base de datos y los mostraremos en una tabla HTML.
Puedes encontrar el código de la aplicación CRUD en GitHub.
Configuración del Host
Lo primero que tenemos que hacer es crear un host virtual en nuestro sistema, que es en donde crearemos el proyecto. Usaremos el servidor Apache, que se instala con Wamp, que es la herramienta que utilizo en este proyecto. Si no sabes cómo crear un host virtual, consulta el tutorial en donde explico cómo crear un host virtual con Apache. En caso de que uses algún paquete todo en uno, consulta una de estas guías.
- Host virtual con Wamp: Cómo crear un host virtual con Wamp
- Host virtual con MAMP: Cómo crear un host virtual con MAMP
- Host virtual con XAMPP: Cómo crear un host virtual con XAMPP
Vamos a crear el host virtual tutorial-crud.localhost
. En mi caso, he asignado el directorio /hosts/tutorial-crud
al host virtual, pero puedes asignar el que prefieras.
Creación de la plantilla HTML
Primero tenemos que crear una plantilla HTML para la aplicación junto con un pequeño menú. No es el objetivo de este tutorial el de aprender CSS, por lo que nos limitaremos a usar Bootstrap para los estilos.
En el interior del directorio del host virtual, crea un archivo vacío llamado index.php
. En teoría deberíamos agregar el código HTML de la aplicación en el archivo index.php
, tal que así:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Aplicación CRUD PHP</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<h1>Aplicación CRUD PHP</h1>
<!-- Aquí el código HTML de la aplicación -->
</body>
</html>
Sin embargo, vamos a dividir la plantilla HTML en una cabecera y un pie que compartirán todas las páginas de nuestra aplicación, por lo que, por ahora, es mejor que dejes el archivo index.php
vacío.
Para ello, crea un directorio llamado /templates
, en cuyo interior debes crear un archivo llamado header.php
y otro llamado footer.php
.
En archivo header.php
contendrá la cabecera de la aplicación, por lo que debes agregar este código HTML:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Aplicación CRUD PHP</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
Lo único que hemos hecho es agregar la declaración DOCTYPE y la sección head
de la aplicación, en donde hemos agregado el título y también hemos incluido Bootstrap desde su CDN.
Seguidamente, debemos agregar el código del archivo footer.php
, que se limitará a cerrar las etiquetas body
y html
con este código:
</body>
</html>
Luego edita el archivo index.php
y modifícalo para que contenga únicamente este código, en donde agregamos el header y el footer que hemos creado:
<?php include "templates/header.php"; ?>
<!-- Aquí el código HTML de la aplicación -->
<?php include "templates/footer.php"; ?>
A continuación vamos configurar la base de datos de la aplicación.
Configuración de la base de datos
Para crear la base datos puedes usar alguna aplicación como MySQL Workbench, SequelPro, Adminer o phpMyAdmin. En este tutorial, primero crearemos la base de datos mediante una consulta SQL.
Crea la base de datos
Crea un directorio en la aplicación llamado /data
y, en su interior, crea un archivo vacío llamado, migracion.sql
. En su interior, agrega esta consulta:
CREATE DATABASE tutorial_crud;
use tutorial_crud;
CREATE TABLE alumnos (
id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(30) NOT NULL,
apellido VARCHAR(30) NOT NULL,
email VARCHAR(50) NOT NULL,
edad INT(3),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Lo que hemos hecho en este script es crear la base de datos, a la que llamamos tutorial_crud
. Luego usamos la sentencia use
para seleccionar la base de datos que hemos creado y luego creamos la tabla alumnos
junto a sus campos. Primero definimos el nombre de los campos y seguidamente su tipo:
- Usamos
int(11)
para definir campos que contengan un número entero con una longitud de hasta 11 números. - Usamos
varchar(n)
para definir cadenas que contengan hastan
caracteres. - Usamos
TIMESTAMP
para definir un campo que contenga una fecha en formatoYYYY-MM-DD HH:MI:SS
.
Los campos created_at
y updated_at
guardarán la fecha de creación y de actualización de los alumnos respectivamente. Además, también hemos usado la sentencia NOT NULL
para evitar que los campos puedan estar vacíos. No será posible insertar un registro en la tabla si un campo NOT NULL
está vacío.
También asignamos la fecha actual como la fecha por defecto de los campos created_at
y updated_at
mediante la sentencia DEFAULT
y el valor CURRENT_TIMESTAMP
.
Si quieres puedes probar la consulta antes de usarla en el código. Para ello sigue estos los pasos que ves a continuación.
- Accede a phpMyAdmin o a la herramienta que utilices:
- Luego accede a la sección que permite ejecutar consulta SQL y copia y pega la consulta anterior:
- Luego ejecuta la consulta haciendo clic en continuar en el caso de phpMyAdmin. Esta consulta debería crear la base de datos.
Si has creado la base de datos y no ha habido errores, significa que todo funciona como debería. Seguidamente borra la base de datos, ya que lo que pretendemos es crearla mediante un script PHP.
Crea el script de instalación
Vamos a crear un script que nos permita conectarnos a MySQL para crear la base de datos. Podemos usar la interfaz PDO (PHP Data Objects) o podemos usar MySQLi. La diferencia consiste en que con PDO nos podemos conectar a más bases de datos que no necesariamente han de ser MySQL, siendo más versátil que MySQLi, que solamente funcionará con bases de datos MySQL. Además, PDO es más extensible y abierto de cara al futuro, haciendo que las aplicaciones sean más fáciles de mantener.
El constructor de la clase PDO necesita que le pasemos el host de conexión a la base de datos, el nombre de usuario MySQL, la contraseña y finalmente las opciones de conexión. Para evitar repetir estos datos en varios archivos, crea el archivo de configuración config.php
en el directorio raíz de la aplicación:
<?php
return [
'db' => [
'host' => 'localhost',
'user' => 'root',
'pass' => 'root',
'name' => 'tutorial_crud',
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]
]
];
Lo que hemos hecho ha sido definir un array de configuración que será vuelto por el archivo. En el array db
hemos definido los parámetros y opciones que usaremos para conectarnos a la base de datos.
Ahora crea un archivo llamado instalar.php
en el directorio raíz del proyecto y, en su interior, incluye el array de configuración y asigna una nueva instancia de la clase PDO a una variable, a la que llamaremos $conexion
. Para crear el objeto PDO usaremos los datos del array de configuración:
$config = include 'config.php';
$conexion = new PDO('mysql:host=' . $config['db']['host'], $config['db']['user'], $config['db']['pass'], $config['db']['options']);
Como ves, el primer parámetro es una cadena de texto que incluye el tipo de la base de datos, el host y opcionalmente el nombre de la base de datos como parte de ella. A este cadena se le llama DSN.
Ahora que ya hemos creado la conexión, vamos a asignar nuestra consulta SQL a una variable usando el método file_get_contents
y, seguidamente, usaremos el método exec
para ejecutar la consulta:
$sql = file_get_contents('data/migracion.sql');
$conexion->exec($sql);
A continuación puedes ver el contenido final del archivo instalar.php
, en el que también hemos agregado un bloque try/catch
para que se muestre algún error en caso de haberlo:
<?php
$config = include 'config.php';
try {
$conexion = new PDO('mysql:host=' . $config['db']['host'], $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$sql = file_get_contents("data/migracion.sql");
$conexion->exec($sql);
echo "La base de datos y la tabla de alumnos se han creado con éxito.";
} catch(PDOException $error) {
echo $error->getMessage();
}
Tal y como ves, la sentencia catch
del bloque try/catch
recibirá una excepción de tipo PDOException
como parámetro.
Ejecuta el script de instalación
Para ejecutar el script de instalación, accede a la URL /instalar.php
desde tu navegador. En mi caso, accederé a la URL tutorial-crud.localhost/instalar.php
. Deberías ver el siguiente mensaje:
Si se muestra un mensaje de error en el que se dice que la base de datos ya existe, recuerda que deberías haberla eliminado desde la aplicación gestora de bases de datos.
Creación de la aplicación CRUD
Tenemos que crear una página que nos permita crear un alumno, otra que nos permita listarlos y otra que nos permita actualizarlos. Además, también necesitaremos un script que sea capaz de eliminar usuarios. Veamos cada uno de estos apartados de la aplicación CRUD por separado.
CRUD (Create): Creación de alumnos
Crea un archivo llamado crear.php
en el directorio raíz de la aplicación. En este archivo agregaremos un formulario que nos permita crear un alumno. Pero primero debemos agregar un enlace al mismo en el archivo index.php
:
<?php include "templates/header.php"; ?>
<div class="container">
<div class="row">
<div class="col-md-12">
<a href="crear.php" class="btn btn-primary mt-4">Crear alumno</a>
<hr>
</div>
</div>
</div>
<?php include "templates/footer.php"; ?>
Lo único que hemos hecho ha sido agregar un botón que nos permita acceder al archivo create.php
.
Formulario HTML
Primero incluiremos los archivos header.php
y footer.php
en el archivo crear.php
. También agregaremos un formulario HTML que nos permita introducir los datos de un alumno:
<?php include "templates/header.php"; ?>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="mt-4">Crea un alumno</h2>
<hr>
<form method="post">
<div class="form-group">
<label for="nombre">Nombre</label>
<input type="text" name="nombre" id="nombre" class="form-control">
</div>
<div class="form-group">
<label for="apellido">Apellido</label>
<input type="text" name="apellido" id="apellido" class="form-control">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" id="email" class="form-control">
</div>
<div class="form-group">
<label for="edad">Edad</label>
<input type="text" name="edad" id="edad" class="form-control">
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Enviar">
<a class="btn btn-primary" href="index.php">Regresar al inicio</a>
</div>
</form>
</div>
</div>
</div>
<?php include "templates/footer.php"; ?>
Hemos agregado el atributo name
a cada campo <input>
del formulario. El valor del atributo name
será el nombre que tendrá cada campo cuando se envíe el formulario.
Hemos agregado también una etiqueta <label>
para cada campo, que se relacionará con su correspondiente campo gracias al atributo for
. El valor del atributo for
es el mismo que el del atributo id
del campo con el que se relaciona. El uso de etiquetas label
permite que las páginas sean más accesibles.
No hemos especificado ninguna acción en el formulario, por lo que éste se enviará a la misma página en la que está definido. Por ahora, dado que todavía no hemos agregado el código PHP, no ocurrirá nada.
Si accedes al proyecto desde tu navegador, este será el resultado del formulario:
Tras crear el formulario, pasaremos a la parte backend, que es el código que ejecutará el servidor para insertar el usuario en la base de datos.
Código PHP
Cuando envías el formulario, los datos se enviarán al propio script crear.php
. Podrás encontrarlos indexados en el interior del array $_POST
. Por ejemplo, el nombre que introduzcas en el campo cuyo atributo name
es nombre
, estará en la variable $_POST['nombre']
. Del mismo modo, el nombre que introduzcas en el campo cuyo atributo name
es apellido
, estará en la variable $_POST['apellido']
.
Para comprobar si el formulario se ha enviado, puedes usar la siguiente sentencia:
if (isset($_POST['submit'])) {
// Acciones a realizar }
Para insertar un usuario también debemos conectarnos a MySQL, pero ahora deberemos especificar también el nombre de la base de datos en el parámetros DSN.
A continuación, agrega este código al inicio del archivo crear.php
:
<?php
if (isset($_POST['submit'])) {
$resultado = [
'error' => false,
'mensaje' => 'Usuario agregado con éxito'
];
$config = include 'config.php';
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
// Código que insertará un alumno
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
El array $resultado
almacenará algún posible error, de haberlo. Luego hemos incluido el array de configuración del archivo config.php
y nos hemos conectado a la base de datos. Esta vez hemos definido el nombre de la base de datos a la que nos conectamos.
Hemos usado un bloque try/catch
, en cuyo interior insertamos el usuario. De haber algún error, se ejecutará el bloque catch
, en donde almacenamos el error en el array resultado
.
Tal y como ves, he escrito un comentario con la localización en la que debes agregar el código encargado de crear un nuevo usuario en la base de datos. Ahora debes crear un array con los datos del nuevo alumno, que obtendremos del array $_POST
:
$alumno = [
"nombre" => $_POST['nombre'],
"apellido" => $_POST['apellido'],
"email" => $_POST['email'],
"edad" => $_POST['edad'],
];
En teoría deberíamos sanitizar los datos de entrada. Sin embargo, dado que usaremos sentencias preparadas de PHP, no es necesario. Usaremos una sentencia INSERT
MySQL:
INSERT INTO users (nombre, apellido, email, edad) values (:nombre, :apellido, :email, :edad)
Este sería el código PHP que implementa la consulta. Hemos usado dos líneas para que sea más legible:
$consultaSQL = "INSERT INTO alumnos (nombre, apellido, email, edad)";
$consultaSQL .= "values (:" . implode(", :", array_keys($alumno)) . ")";
A continuación vamos a usar el método prepare
y a ejecutar la consulta:
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute($alumno);
Vamos a agregar también un mensaje de confirmación justo después del lugar en el que incluimos el archivo header.php
, en donde mostraremos un error, de haberlo, o un mensaje de éxito si el alumno se ha insertado correctamente:
<?php
if (isset($resultado)) {
?>
<div class="container mt-3">
<div class="row">
<div class="col-md-12">
<div class="alert alert-<?= $resultado['error'] ? 'danger' : 'success' ?>" role="alert">
<?= $resultado['mensaje'] ?>
</div>
</div>
</div>
</div>
<?php
}
?>
Este sería el código PHP completo que usamos para crear el usuario:
<?php
if (isset($_POST['submit'])) {
$resultado = [
'error' => false,
'mensaje' => 'El alumno ' . $_POST['nombre'] . ' ha sido agregado con éxito'
];
$config = include 'config.php';
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$alumno = array(
"nombre" => $_POST['nombre'],
"apellido" => $_POST['apellido'],
"email" => $_POST['email'],
"edad" => $_POST['edad'],
);
$consultaSQL = "INSERT INTO alumnos (nombre, apellido, email, edad)";
$consultaSQL .= "values (:" . implode(", :", array_keys($alumno)) . ")";
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute($alumno);
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
?>
<?php include "templates/header.php"; ?>
<?php
if (isset($resultado)) {
?>
<div class="container mt-3">
<div class="row">
<div class="col-md-12">
<div class="alert alert-<?= $resultado['error'] ? 'danger' : 'success' ?>" role="alert">
<?= $resultado['mensaje'] ?>
</div>
</div>
</div>
</div>
<?php
}
?>
Ahora ya podrías enviar el formulario. Deberías ver el siguiente mensaje una vez lo envíes:
Si embargo, todavía podemos mejorar el formulario.
Ataques XSS
Cuando creamos un alumno con éxito, mostramos su nombre en el mensaje de confirmación. Imprimimos por pantalla directamente el resultado de la variable $_POST
, lo cual podría tener ciertos efectos indeseables si algún atacante inyecta código malicioso en esta variable.
Para evitar ataques XSS vamos a codificar los caracteres especiales en sus respectivas versiones HTML. Para simplificar el proceso, crearemos una función reutilizable.
Crea el archivo funciones.php
en el directorio raíz del proyecto y agrega esta función:
function escapar($html) {
return htmlspecialchars($html, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8");
}
Lo que hace la función es codificar cualquier caracter en su versión HTML. Luego, incluye el archivo funciones.php
en la parte superior del archivo create.php
:
include 'funciones.php';
Seguidamente, usa la función escapar
con el elemento $_POST['nombre']
en el array $resultado
:
$resultado = [
'error' => false,
'mensaje' => 'El alumno ' . escapar($_POST['nombre']) . ' ha sido agregado con éxito'
];
Este sería el código final completo del archivo crear.php
:
<?php
include 'funciones.php';
if (isset($_POST['submit'])) {
$resultado = [
'error' => false,
'mensaje' => 'El alumno ' . escapar($_POST['nombre']) . ' ha sido agregado con éxito'
];
$config = include 'config.php';
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$alumno = array(
"nombre" => $_POST['nombre'],
"apellido" => $_POST['apellido'],
"email" => $_POST['email'],
"edad" => $_POST['edad'],
);
$consultaSQL = "INSERT INTO alumnos (nombre, apellido, email, edad) values (:" . implode(", :", array_keys($alumno)) . ")";
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute($alumno);
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
?>
<?php include 'templates/header.php'; ?>
<?php
if (isset($resultado)) {
?>
<div class="container mt-3">
<div class="row">
<div class="col-md-12">
<div class="alert alert-<?= $resultado['error'] ? 'danger' : 'success' ?>" role="alert">
<?= $resultado['mensaje'] ?>
</div>
</div>
</div>
</div>
<?php
}
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="mt-4">Crea un alumno</h2>
<hr>
<form method="post">
<div class="form-group">
<label for="nombre">Nombre</label>
<input type="text" name="nombre" id="nombre" class="form-control">
</div>
<div class="form-group">
<label for="apellido">Apellido</label>
<input type="text" name="apellido" id="apellido" class="form-control">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" id="email" class="form-control">
</div>
<div class="form-group">
<label for="edad">Edad</label>
<input type="text" name="edad" id="edad" class="form-control">
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Enviar">
<a class="btn btn-primary" href="index.php">Regresar al inicio</a>
</div>
</form>
</div>
</div>
</div>
<?php include 'templates/footer.php'; ?>
CRUD (Read): Lista de alumnos
Vamos a crear la página usada para mostrar los datos de los alumnos. Para ello usaremos el archivo index.php
, en donde incluiremos tanto el archivo header.php
como el archivo footer.php
.
Código PHP
Después del botón que nos permite acceder a la página crear.php
vamos a agregar una tabla con la lista de alumnos existentes. Sin embargo, primero necesitamos obtener la lista de alumnos desde la base de datos. Por ello, debes agregar este código al principio del archivo index.php
:
<?php
include 'funciones.php';
$error = false;
$config = include 'config.php';
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
// Código que obtendrá la lista de alumnos
} catch(PDOException $error) {
$error = $error->getMessage();
}
?>
Lo que hemos hecho ha sido incluir el archivo funciones.php
y también el array de configuración. Luego nos conectamos a la base de datos en un bloque try/catch
. De haber algún error, lo almacenamos en la variable $error
.
La consulta MySQL que usaremos para obtener la lista de alumnos será la siguiente, que sencillamente obtendrá la lista completa de alumnos
$sql = "SELECT * FROM alumnos;
Este será el código PHP que implementa y ejecuta la consulta:
$consultaSQL = "SELECT * FROM alumnos";
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
Luego almacenamos el resultado en la variable $alumnos
:
$alumnos = $sentencia->fetchAll();
En caso de que se produzca algún error debes mostrarlo. Para ello, agrega el siguiente código justo después del lugar en donde incluimos el archivo header.php
:
<?php
if ($error) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $error ?>
</div>
</div>
</div>
</div>
<?php
}
?>
Este sería el código PHP del archivo index.php
con lo que hemos hecho hasta ahora.
<?php
include 'funciones.php';
$error = false;
$config = include 'config.php';
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$consultaSQL = "SELECT * FROM alumnos";
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
$alumnos = $sentencia->fetchAll();
} catch(PDOException $error) {
$error= $error->getMessage();
}
?>
<?php include "templates/header.php"; ?>
<?php
if ($error) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $error ?>
</div>
</div>
</div>
</div>
<?php
}
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<a href="crear.php" class="btn btn-primary mt-4">Crear alumno</a>
<hr>
</div>
</div>
</div>
<?php include "templates/footer.php"; ?>
Ahora ya solamente nos falta mostrar los resultados en una tabla.
Tabla HTML
Vamos a mostrar la lista de alumnos en una tabla HTML. Sin embargo, primero agregaremos un mensaje que se ejecute en caso de que se haya producido algún error al obtener la lista de alumnos.
A continuación puedes ver el código de la tabla. Agrega este código justo después del bloque en donde mostramos el botón que redirige a la página que permite crear alumnos, y antes del lugar en donde incluimos el archivo footer.php
:
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="mt-3">Lista de alumnos</h2>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Nombre</th>
<th>Apellido</th>
<th>Email</th>
<th>Edad</th>
</tr>
</thead>
<tbody>
<?php
if ($alumnos && $sentencia->rowCount() > 0) {
foreach ($alumnos as $fila) {
?>
<tr>
<td><?php echo escapar($fila["id"]); ?></td>
<td><?php echo escapar($fila["nombre"]); ?></td>
<td><?php echo escapar($fila["apellido"]); ?></td>
<td><?php echo escapar($fila["email"]); ?></td>
<td><?php echo escapar($fila["edad"]); ?></td>
</tr>
<?php
}
}
?>
<tbody>
</table>
</div>
</div>
</div>
Lo que hacemos es comprobar que existen alumnos mediante el método rowCount
y recorrer la lista de alumnos, agregando una fila a la tabla por cada uno de los alumnos.
Este sería el código del archivo index.php
con lo que hemos hecho hasta ahora:
<?php
include 'funciones.php';
$error = false;
$config = include 'config.php';
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$consultaSQL = "SELECT * FROM alumnos";
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
$alumnos = $sentencia->fetchAll();
} catch(PDOException $error) {
$error= $error->getMessage();
}
?>
<?php include "templates/header.php"; ?>
<?php
if ($error) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $error ?>
</div>
</div>
</div>
</div>
<?php
}
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<a href="crear.php" class="btn btn-primary mt-4">Crear alumno</a>
<hr>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="mt-3">Lista de alumnos</h2>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Nombre</th>
<th>Apellido</th>
<th>Email</th>
<th>Edad</th>
</tr>
</thead>
<tbody>
<?php
if ($alumnos && $sentencia->rowCount() > 0) {
foreach ($alumnos as $fila) {
?>
<tr>
<td><?php echo escapar($fila["id"]); ?></td>
<td><?php echo escapar($fila["nombre"]); ?></td>
<td><?php echo escapar($fila["apellido"]); ?></td>
<td><?php echo escapar($fila["email"]); ?></td>
<td><?php echo escapar($fila["edad"]); ?></td>
</tr>
<?php
}
}
?>
<tbody>
</table>
</div>
</div>
</div>
<?php include "templates/footer.php"; ?>
Si agregas algunos alumnos y luego accedes a la página principal de la aplicación usando tu navegador, deberías ver este resultado:
Ya hemos terminado, pero vamos a agregar una funcionalidad a mayores. Se trata de un formulario que nos permitirá filtrar la lista de alumnos.
Búsqueda
Estaría bien agregar un campo de búsqueda que nos permita buscar usuarios por apellido. Para ello crearemos el siguiente formulario debajo de la línea de separación que hemos agregado, debajo del enlace hacia la página crear.php
:
<div class="container">
<div class="row">
<div class="col-md-12">
<a href="crear.php" class="btn btn-primary mt-4">Crear alumno</a>
<hr>
<form method="post" class="form-inline">
<div class="form-group mr-3">
<input type="text" id="apellido" name="apellido" placeholder="Buscar por apellido" class="form-control">
</div>
<button type="submit" name="submit" class="btn btn-primary">Ver resultados</button>
</form>
</div>
</div>
</div>
Hemos usado el atributo placeholder
en el campo nombre
del formulario para mostrar un texto por defecto, que desaparecerá cuando introduzcamos algo en él.
Seguidamente, accede al proyecto desde tu navegador para ver el resultado:
El formulario enviará el apellido del alumno que introduzcamos a la propia página, por lo que debemos agregar una consulta SQL alternativa que se ejecute cuando el formulario se haya enviado:
if (isset($_POST['apellido'])) {
$consultaSQL = "SELECT * FROM alumnos WHERE apellido LIKE '%" . $_POST['apellido'] . "%'";
} else {
$consultaSQL = "SELECT * FROM alumnos";
}
El operador MySQL LIKE
buscará los alumnos cuyo apellido contenga la subadena que introduzcamos en el campo apellido
. El símbolo %
sirve para especificar que puede haber texto a la izquierda o a la derecha de la cadena.
Vamos a modificar también el título del formulario, de modo que indiquemos cuando estemos realizando una búsqueda por apellido. Para ello, asignaremos el título del formulario mediante PHP:
$titulo = isset($_POST['apellido']) ? 'Lista de alumnos (' . $_POST['apellido'] . ')' : 'Lista de alumnos';
Hemos usado el operador ternario de PHP para comprobar si el apellido está presente en el array $_POST,
en cuyo caso agregamos el apellido entre paréntesis al título:
Por ahora hemos visto cómo conectarnos a la base de datos mediante PDO, cómo crear un script de instalación y cómo listar y agregar registros. En una aplicación real también tendríamos que agregar gestión de usuarios, una página de login o validaciones JavaScript entre otras cosas, aunque es algo que sale del alcance de este tutorial.
Acciones
Antes de continuar, vamos a agregar una columna más a nuestra tabla que contenga dos enlaces para cada fila. Los enlaces enlazarán al archivo editar.php
y al archivo borrar.php
respectivamente. Para ello agregamos una cabecera adicional a la tabla:
<thead>
<tr>
<!-- ... -->
<th>Acciones</th>
</tr>
</thead>
También agregaremos una columna más con las acciones al cuerpo de la tabla:
<td>
<a href="<?= 'borrar.php?id=' . escapar($fila["id"]) ?>">🗑️Borrar</a>
<a href="<?= 'editar.php?id=' . escapar($fila["id"]) ?>">✏️Editar</a>
</td>
Tal y como ves, enviamos el id
del usuario que queremos borrar o que queremos actualizar a las páginas borrar.php
y editar.php
respectivamente. Estas páginas todavía nos las hemos creado.
Este será el resultado:
Este es el código completo final del archivo index.php
:
<?php
include 'funciones.php';
$error = false;
$config = include 'config.php';
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
if (isset($_POST['apellido'])) {
$consultaSQL = "SELECT * FROM alumnos WHERE apellido LIKE '%" . $_POST['apellido'] . "%'";
} else {
$consultaSQL = "SELECT * FROM alumnos";
}
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
$resultados = $sentencia->fetchAll();
} catch(PDOException $error) {
$error= $error->getMessage();
}
$titulo = isset($_POST['apellido']) ? 'Lista de alumnos (' . $_POST['apellido'] . ')' : 'Lista de alumnos';
?>
<?php include "templates/header.php"; ?>
<?php
if ($error) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $error ?>
</div>
</div>
</div>
</div>
<?php
}
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<a href="crear.php" class="btn btn-primary mt-4">Crear alumno</a>
<hr>
<form method="post" class="form-inline">
<div class="form-group mr-3">
<input type="text" id="apellido" name="apellido" placeholder="Buscar por apellido" class="form-control">
</div>
<button type="submit" name="submit" class="btn btn-primary">Ver resultados</button>
</form>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="mt-3"><?= $titulo ?></h2>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Nombre</th>
<th>Apellido</th>
<th>Email</th>
<th>Edad</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php
if ($alumnos && $sentencia->rowCount() > 0) {
foreach ($alumnos as $fila) {
?>
<tr>
<td><?php echo escapar($fila["id"]); ?></td>
<td><?php echo escapar($fila["nombre"]); ?></td>
<td><?php echo escapar($fila["apellido"]); ?></td>
<td><?php echo escapar($fila["email"]); ?></td>
<td><?php echo escapar($fila["edad"]); ?></td>
<td>
<a href="<?= 'borrar.php?id=' . escapar($fila["id"]) ?>">🗑️Borrar</a>
<a href="<?= 'editar.php?id=' . escapar($fila["id"]) ?>" . >✏️Editar</a>
</td>
</tr>
<?php
}
}
?>
<tbody>
</table>
</div>
</div>
</div>
<?php include "templates/footer.php"; ?>
CRUD (Update): Actualización de alumnos
Vamos a agregar una página que nos permita editar un usuario. Para ello crea el archivo editar.php
en la carpeta raíz del proyecto con este contenido:
<?php require "templates/header.php"; ?>
<!-- código de la página -->
<?php require "templates/footer.php"; ?>
Necesitamos obtener los datos del usuario que estamos editando desde la base de datos y mostrar un formulario de edición.
Código PHP (Lectura)
Primero incluimos el archivo funciones.php
y el array de configuración. Seguidamente comprobamos que el parámetro $_GET['id']
esté presente, mostrando un error en caso contrario. Luego nos conectamos a la base de datos para buscar el alumno que estamos editando.
Este es el código PHP que usamos para obtener el alumno que estamos editando, que va al principio del archivo editar.php
:
<?php
include 'funciones.php';
$config = include 'config.php';
$resultado = [
'error' => false,
'mensaje' => ''
];
if (!isset($_GET['id'])) {
$resultado['error'] = true;
$resultado['mensaje'] = 'El alumno no existe';
}
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$id = $_GET['id'];
$consultaSQL = "SELECT * FROM alumnos WHERE id =" . $id;
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
$alumno = $sentencia->fetch(PDO::FETCH_ASSOC);
if (!$alumno) {
$resultado['error'] = true;
$resultado['mensaje'] = 'No se ha encontrado el alumno';
}
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
?>
Tal y como ves, en caso de no pasar ningún id
a la página o de que ocurra algún error, almacenamos el mensaje en el elemento $resultado['mensaje']
.
Formulario HTML
A continuación debemos agregar un formulario con los datos actuales del alumno que hemos obtenido desde la base de datos, que están en el array $alumno
. Este formulario es casi idéntico al que hemos agregado en el archivo crear.php
, con la salvedad de que en este caso los campos tendrán un valor.
Sin embargo, primero debemos mostrar algún error en caso de que haya ocurrido alguno. Para ello usa el siguiente código después de la línea en la que incluimos el archivo header.php
:
<?php
if ($resultado['error']) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $resultado['mensaje'] ?>
</div>
</div>
</div>
</div>
<?php
}
?>
En caso de que se haya enviado el formulario, tendremos que mostrar también un mensaje de confirmación siempre y cuando no haya habido errores:
<?php
if (isset($_POST['submit']) && !$resultado['error']) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-success" role="alert">
El alumno ha sido actualizado correctamente
</div>
</div>
</div>
</div>
<?php
}
?>
Seguidamente, tras los mensajes anteriores, agrega el código del formulario:
<?php
if (isset($alumno) && $alumno) {
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="mt-4">Editando el alumno <?= escapar($alumno['nombre']) . ' ' . escapar($alumno['apellido']) ?></h2>
<hr>
<form method="post">
<div class="form-group">
<label for="nombre">Nombre</label>
<input type="text" name="nombre" id="nombre" value="<?= escapar($alumno['nombre']) ?>" class="form-control">
</div>
<div class="form-group">
<label for="apellido">Apellido</label>
<input type="text" name="apellido" id="apellido" value="<?= escapar($alumno['apellido']) ?>" class="form-control">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" id="email" value="<?= escapar($alumno['email']) ?>" class="form-control">
</div>
<div class="form-group">
<label for="edad">Edad</label>
<input type="text" name="edad" id="edad" value="<?= escapar($alumno['edad']) ?>" class="form-control">
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Actualizar">
<a class="btn btn-primary" href="index.php">Regresar al inicio</a>
</div>
</form>
</div>
</div>
</div>
<?php
}
?>
Tal y como ves, solamente mostramos el formulario en caso de que se haya obtenido un alumno. Hemos usado el atributo value
de los campos input
HTML para definir el valor que tendrá cada campo.
Código PHP (Actualización)
Ahora que ya tenemos el formulario debemos definir las acciones a ejecutar cuando se envíe. Para ello, debemos detectar si el parámetro $_POST['submit']
está presente. Si es así, nos conectamos a la base de datos y actualizamos el alumno con los nuevos datos. Para completar esta tarea, agrega el siguiente código justo antes del bloque try/catch
en el que obtenemos los datos del alumno:
if (isset($_POST['submit'])) {
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
// actualización del alumno
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
Ahora usaremos una sentencia SQL UPDATE
para actualizar los valores del alumno cuyo id
se corresponde con el que estamos editando:
UPDATE alumnos
SET nombre = :nombre,
apellido = :apellido,
email = :email,
edad = :edad
updated_at = NOW()
WHERE id = :id
Tal y como ves, también actualizamos el campo updated_at
con la fecha actual, que obtenemos mediante la función NOW()
de MySQL. Este sería el código PHP que implementa la consulta anterior:
$alumno = [
"id" => $_GET['id'],
"nombre" => $_POST['nombre'],
"apellido" => $_POST['apellido'],
"email" => $_POST['email'],
"edad" => $_POST['edad']
];
$consultaSQL = "UPDATE alumnos SET
nombre = :nombre,
apellido = :apellido,
email = :email,
edad = :edad,
updated_at = NOW()
WHERE id = :id";
$consulta = $conexion->prepare($consultaSQL);
$consulta->execute($alumno);
Y con esto ya habremos actualizado los datos del alumno.
Este sería el resultado cuando editas un alumno correctamente:
Este es el código completo final del archivo editar.php
:
<?php
include 'funciones.php';
$config = include 'config.php';
$resultado = [
'error' => false,
'mensaje' => ''
];
if (!isset($_GET['id'])) {
$resultado['error'] = true;
$resultado['mensaje'] = 'El alumno no existe';
}
if (isset($_POST['submit'])) {
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$alumno = [
"id" => $_GET['id'],
"nombre" => $_POST['nombre'],
"apellido" => $_POST['apellido'],
"email" => $_POST['email'],
"edad" => $_POST['edad']
];
$consultaSQL = "UPDATE alumnos SET
nombre = :nombre,
apellido = :apellido,
email = :email,
edad = :edad,
updated_at = NOW()
WHERE id = :id";
$consulta = $conexion->prepare($consultaSQL);
$consulta->execute($alumno);
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$id = $_GET['id'];
$consultaSQL = "SELECT * FROM alumnos WHERE id =" . $id;
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
$alumno = $sentencia->fetch(PDO::FETCH_ASSOC);
if (!$alumno) {
$resultado['error'] = true;
$resultado['mensaje'] = 'No se ha encontrado el alumno';
}
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
?>
<?php require "templates/header.php"; ?>
<?php
if ($resultado['error']) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $resultado['mensaje'] ?>
</div>
</div>
</div>
</div>
<?php
}
?>
<?php
if (isset($_POST['submit']) && !$resultado['error']) {
?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-success" role="alert">
El alumno ha sido actualizado correctamente
</div>
</div>
</div>
</div>
<?php
}
?>
<?php
if (isset($alumno) && $alumno) {
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2 class="mt-4">Editando el alumno <?= escapar($alumno['nombre']) . ' ' . escapar($alumno['apellido']) ?></h2>
<hr>
<form method="post">
<div class="form-group">
<label for="nombre">Nombre</label>
<input type="text" name="nombre" id="nombre" value="<?= escapar($alumno['nombre']) ?>" class="form-control">
</div>
<div class="form-group">
<label for="apellido">Apellido</label>
<input type="text" name="apellido" id="apellido" value="<?= escapar($alumno['apellido']) ?>" class="form-control">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" id="email" value="<?= escapar($alumno['email']) ?>" class="form-control">
</div>
<div class="form-group">
<label for="edad">Edad</label>
<input type="text" name="edad" id="edad" value="<?= escapar($alumno['edad']) ?>" class="form-control">
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-primary" value="Actualizar">
<a class="btn btn-primary" href="index.php">Regresar al inicio</a>
</div>
</form>
</div>
</div>
</div>
<?php
}
?>
<?php require "templates/footer.php"; ?>
CRUD (Delete): Borrado de alumnos
Vamos a agregar una página que nos permita borrar un alumno de la base de datos. Para ello crea el archivo borrar.php
en la carpeta raíz del proyecto con este contenido:
<?php require "templates/header.php"; ?>
<!-- código de la página -->
<?php require "templates/footer.php"; ?>
Lo que haremos será ejecutar una consulta que borre el alumno cuyo id
se corresponde con el parámetro $_GET['id']
. Si el alumno es borrado con éxito redirigiremos al usuario a la página index.php
. De lo contrario mostraremos un mensaje de e error.
Código PHP
Primero vamos a conectarnos a la base de datos y a borrar el alumno, para luego usar la función header
para redirigir al usuario al archivo index.php
. Agrega este código antes de la línea en la que incluimos el archivo header.php
:
<?php
include 'funciones.php';
$config = include 'config.php';
$resultado = [
'error' => false,
'mensaje' => ''
];
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$id = $_GET['id'];
$consultaSQL = "DELETE FROM alumnos WHERE id =" . $id;
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
header('Location: /index.php');
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
?>
Código HTML
El siguiente código HTML solamente se mostrará si ha ocurrido algún error. Agrega este código después de la línea donde incluimos el archivo header.php
:
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $resultado['mensaje'] ?>
</div>
</div>
</div>
</div>
Y con esto ya hemos terminado. Este sería el código completo final del archivo borrar.php
:
<?php
include 'funciones.php';
$config = include 'config.php';
$resultado = [
'error' => false,
'mensaje' => ''
];
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'], $config['db']['pass'], $config['db']['options']);
$id = $_GET['id'];
$consultaSQL = "DELETE FROM alumnos WHERE id =" . $id;
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
header('Location: /index.php');
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
?>
<?php require "templates/header.php"; ?>
<div class="container mt-2">
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger" role="alert">
<?= $resultado['mensaje'] ?>
</div>
</div>
</div>
</div>
<?php require "templates/footer.php"; ?>
Protección CSRF
Vamos a agregar protección contra ataques CSRF, mediante los cuales un atacante puede engañar al navegador y ejecutar código no deseado. Lo que haremos será almacenar un token CSRF en una variable de sesión del servidor. Validaremos el token del servidor contra un valor que agregaremos en un campo oculto de los formulario de la aplicación.
Edita el archivo funciones.php
y agrega esta función, en la que generamos un token que almacenamos en la variable de sesión $_SESSION['csrf']
:
function csrf() {
session_start();
if (empty($_SESSION['csrf'])) {
if (function_exists('random_bytes')) {
$_SESSION['csrf'] = bin2hex(random_bytes(32));
} else if (function_exists('mcrypt_create_iv')) {
$_SESSION['csrf'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
} else {
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(32));
}
}
}
Puede que no estén disponibles ciertas funciones en tu sistema, por lo que intentamos generar el token de sesión con varias de las funciones más habituales.
Luego, agrega este código tras incluir el archivo funciones.php
en todas las páginas de la aplicación.
include 'funciones.php';
csrf();
if (isset($_POST['submit']) && !hash_equals($_SESSION['csrf'], $_POST['csrf'])) {
die();
}
Lo que hemos hecho es comprobar que el token CSRF de sesión sea igual que el que agregaremos en el formulario. Si no es igual, finalizamos la ejecución de la aplicación.
Luego, agrega este campo oculto a los formularios de la aplicación:
<input name="csrf" type="hidden" value="<?php echo escapar($_SESSION['csrf']); ?>">
Al usar el atributo hidden
, el campo se mantendrá oculto.
Conclusión
Y con esto ya habrás creado tu primera aplicació CRUD. Es más que recomendable saber programar correctamente con PHP antes de aventurarse en el uso de frameworks aunque a priori pueda paracer que usarlos es más sencillo. De este modo, tendrás una idea más clara de lo que ocurre.
Esta aplicación todavía necesitaría más elementos para ser segura y poder ser usada en producción, pero es una introducción que te resultará muy útil.
Recuerda que puedes consultar el código completo de la aplicación CRUD en GitHub.
Esto ha sido todo.
Gracias
probando para un test de comentarios-usuarios
Soy el usuario Alex con diferente nombre
Amigo un fuerte abrazo, no te imaginas lo que he googleado, llevo una semana y todo lo que ví de crear un CRUD con ninguna explicacion habia podido entenderla. Ni a mi profesor, jajaja pero Sobre todo por que siempre se saltan pasos o hacen el codigo muy poco entendible, pero tengo muchasss cosas que agradecerte Y el explicar lo que hace cada linea, eso tambien es maravilloso, pero hay algo que fue lo que más me sorprendio de este post y es :
$consultaSQL = «INSERT INTO persona (ID_PERSONA,PRIMER_NOMB,SEGUNDO_NOMB,PRIMER_APELL,SEGUNDO_APELL,DIRECCION,NUMERO_TELEFONO,EMAIL)»;
$consultaSQL .= «VALUES (:» . implode(«, :», array_keys($alumno)) . «)»;
este trozo de código tan simple pero tan fácil de aprender, para insertar todos los campos en una tabla es realmente fenomenal..no esta estructurado como siempre lo vez en internet, en serio hermano Mil gracias Mil…Desde Mi Colombia del Alma un Abrazo PARCERO!!!!…
PD: Sigue cambiando el Mundo!!!
Muchas gracias por tu comentario. Intento redactar los tutoriales que a mi me gustaría haber tenido 😀
Pues lo has logrado. Tengo casi un año buscando un tutorial que aclarara, no que confundiera. Está muy completo, y por fin sé lo que estoy haciendo cada vez que uso el CRUD. Sigue haciendo tutoriales, te seguiremos y compartiremos.
Realmente excelente el Tutorial. Quisiera saber qué faltaría para ponerlo en producción?
Felicidades y muchas gracias Edu
Muchas gracias! Excelente explicación me fue de gran ayuda.
EXCELENTE Aporte para los que apenas comenzamos, pero como?, ya teniendo este proyecto pudiera publicarlo en algún host con dominio de los gratuitos, me atrevo a solicitarte un paso paso ya que eres uno de los pocos que las explicaciones se entienden a las mil maravillas, y con esto poder llevar a otro nivel este gran tuturial de CRUD en php.
Else { por lo menos tenerlo en cuenta para futuros tutos, por que sabes que la expresión MAXIMA de hacer estos proyectos web es verlos publicados.}
GRACIAS!!!! COMPADRE
Estimado Edu, muchas gracias por tu tutorial, es de mucha ayuda para los que recién empezamos, bendiciones.
Excelente aporte, GRACIAS por compartir tu conocimiento con nosotros.
Muchas gracias desde Cuba. No había encontrado un tutorial tan completo en internet. Gracias, he aprendido un monton con su dominio en la materia. Muchos cobran por enseñar y usted tiene la virtud de compartir y enseñar de forma gratuita sus conocimientos, Gracias por su altruismo.
Hola, como se haría un read con varios filtros, es decir, buscando a la vez por nombre y apellido por ejemplo?.
Muy buen tutorial, lo estoy haciendo y no quise hacer solo copiar y pegar, sino ir analizando bien el codigo con las explicaciones. Creo que hay un error en la parte que dice «Este es el código completo final del archivo index.php:» en la linea de codigo:
$resultados = $sentencia->fetchAll();
en donde en lugar de $resultados debe ir la variable $alumnos, o sea:
$alumnos = $sentencia->fetchAll();
por lo menos a mi de la otra forma no me resultaba y al ponerme a descubrir porqué no funcionaba vi que la que va es $alumnos
Puede ser? Capaz que al final lo aclara, pero todavía no he llegado al final porque como dije, voy intentando comprender el código 😅
Gracias por tu tiempo
EXCELENTE, estuve revisando y no me funcionaba, con tu comentario funciono!!!!!!
Hola Edu.
Antes de nada, estoy empezando a aprender php y creo que te acostumbras a lo que te enseñan, y si te lo enseñan mal te cuesta el triple aprender, desaprender y aprender de nuevo.
Me encanta tu código y las buenas prácticas que aplicas. Incluso me parece que haces que php sea bonito de ver. Tal vez sea la percepción de un principiante.
Tenía una pregunta chorra que me llama mucho la atención. ¿Por qué haces con comillas simples y el require con dobles?
La verdad es que con php pierdo demasiado tiempo intentando resolver dudas chorras como ésta para acostumbrarme a un buen estilo y prácticas desde el principio. Me da la impresión que, con tantos recursos como hay en php, es todo muy anárquico. Esto no pasa en otros lenguajes.
hola! realmente me ha encantado estoy probando para hacer en mi colegio uno, pero tengo dos dudas,
1) si quisiera que cuando doy de alta un alumno, pudiera a su vez, tocar un botón, donde me permita agregarle al alumno un detalle, por ejemplo, de una lista desplegable, que me permita seleccionar » comportamiento:» y se pueda elegir «bueno, muy bueno, malo.. etc… de una lista desplegable la cual viene de una tabla llamada «conducta», y su columnas «id» y «detalle» donde ahi dice, id- 1- detalle: bueno. id 2.- detalle: malo. etc.
2) que permita ingresar alumnos ya cargados en una base de dato, donde «alumnos» y en las columnas» ID, DNI, SEXO, NOMBREYAPELLIDO». y si no esta, me permita ingresarlo a mano. gracias.
Excelente muchas gracias.
Genio! Muchas gracias por compartirlo, logre seguirlo a la perfección y me resulto muy útil.
Saludos desde Argentina.
Edu, muchas gracias por esa excelente metodología, es muy clara y fácil de entender, he ido realizando la actividad a medida que voy leyendo y ha sido en verdad muy instructivo y motivante para mi.
Tengo una duda, ¿si tengo varios CRUD para hacer, como debo organizar los archivos?, disculpa mi ignorancia, pero apenas estoy empezando en este nuevo mundo web.
Nuevamente MUCHAS GRACIAS.
Muchas gracias Edu por la excelente guía para aprender a hacer CRUD.
Por si sirve, en el punto Ataques XSS, cuando se carga la primer función , deberías agregarle la apertura al PHP de la función. Es obvio para los que ya saben pero no se si para los novatos.
Estimado Edu
Muchas gracias por la contribución. Fue muy didáctica la explicación.
Tengo una consulta la cual en la realidad es un complemento a lo ya explicado.
En la tabla original Alumnos se ha considerado el campo ‘created_at’ el cual no se usa en todas las rutinas explicadas. Como su nombre lo indica, es una campo para almacenar la fecha de creación del registro. Al respecto propongo añadir las siguientes líneas de instrucción:
$hoy = NOW();
$last_id = $conexion->lastInserted();
$consultaSQL2 = «UPDATE Alumnos SET created_at = «.$hoy.» WHERE id = «.$last_id.» «;
$query_success = $conexion->query($consultaSQL2);
De todas formas, va a ser interesante conocer tu apreciación sobre las líneas de código escritas.
Atentamente,
Fernando Díaz
Buenas Fernando
Si te fijas en como esta creada la tabla en MySQL pone
» created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,»
es decir por defecto le pone el valor current_timestamp o valor de fecha actual.
No hace falta hacer nada desde el codigo.
La diferencia con el update es que puedes tener varios update en el tiempo y ahi si tienes que cambiar el valor
Muchas gracias por el tutorial, muy bueno.
Tengo una duda, es posible en el código php ejecutar un query que tenga tablas temporales?, quiero que desde la pagina web se visualice un reporte, y este lo tengo en query. He tratado pero me sale error.
O debo crear un procedimiento almacenado para invocarlo.
Gracias,
hola ammm si todo lo hisiste en el index para que los demas documentos pense que arias un menu en el index y buscarias la funcin de cada boton!!!
y por que lamas tantas vese a la conexion de la db ???
muchas lineas lo hace un poco complicado es solo una observacion que pena.
pero aun asi aprendi aserca de pdo gracias !!!
¡Muchas gracias por tu aportación!
Tus tutoriales me estan sirviendo demsiado.
Un abrazo
Hola
En la parte de búsqueda no sé donde debo insertar la consulta y el $título en el Index.php
Gracias men de mucho provecho, Dios te de muchas cosas buenas.
Excelente gracias, saludos desde venezuela
Me parece muy util, aunque en el formulario de crear deberia tener un campo con select que muestre dos campos dentro del mismo formulario, ejemplo select codigo, ciudad de la tabla ciudades, mostrara codigo y ciudad. Necesito codigo fuente para otro programa, puedo contar con usted, precio. muy amable, gracias
Buenisimo !!! Tengo mas de una semana viendo tutoriales y entendia muy poco o casi nada, vi un curso en youtube y empece a entender mas, tu lo llevaste a lo que necesitaba de la manera mas clara, solo me falta implementarlo en kubernetes y termine una tarea para la clase. Muchas gracias.
thanks
Saludos. Excelente trabajo.
Felicidades Edu Lazaro.
Quisiera consultarte algo si es posible en la parte de editar ya que no me esta funcionando y me ha arrojado error al momento de dar clic sobre el registro a editar
Hola, en la parte de busqueda que dice:
1.El formulario enviará el apellido del alumno que introduzcamos a la propia página, por lo que debemos agregar una consulta SQL… ¿donde agrego el codigo?:
if (isset($_POST[‘apellido’])) {
$consultaSQL = «SELECT * FROM alumnos WHERE apellido LIKE ‘%» . $_POST[‘apellido’] . «%'»;
} else {
$consultaSQL = «SELECT * FROM alumnos»;
}
2. tambien donde dice: Vamos a modificar también el título del formulario ¿donde agrego el codigo?:
$titulo = isset($_POST[‘apellido’]) ? ‘Lista de alumnos (‘ . $_POST[‘apellido’] . ‘)’ : ‘Lista de alumnos’;
¿Alguien me ayuda?
Un Millón de Gracias amigo me Funciono perfectamente mejor tutorial que pude ver que te aclara las dudas en vez de ocasionarte mas, Tenia 3 semanas tratando de conseguir uno que me explicara lo que esta en este y que fuera especifico pero no encontré ninguno solo este y lo que otros no pudieron explicar con palabras vos lo hiciste con texto lo que requiere de paciencia y dedicación, millones de Gracias ya que de eso dependia una parte de mi proyecto de la uni, necesitaba la implementación de un crud pero no me gusta el copia y pega sin ninguna explicación porque uno no entiende que fue lo que hizo pero este no entro en esa categoría saludos amigo desde Venezuela.
EXCELENTE
Todo funciona perfectamente. Muy buena pedagogía para explicar cada detalle. Gracias Edu por tu maravilloso tutorial de Programacion PHP. Sigue adelante compartiendo tu sabiduría con nosotros: los que vamos paso a paso por esta senda
del aprendizaje autodidacta y así tener una profesión y un mejor ingreso económico.
Gracias y hasta pronto.