Programar Trabajo
Programar Trabajo
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.
Contenidos
1 Introducción
2 Configuración del Host
3 Creación de la plantilla HTML
4 Configuración de la base de datos
o 4.1 Crea la base de datos
5.2.3 Búsqueda
5.2.4 Acciones
o 5.3 CRUD (Update): Actualización de alumnos
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.
<!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" />
<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.
<!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" />
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/
bootstrap.min.css" />
</head>
<body>
</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.
use tutorial_crud;
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.
<?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.
$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.
<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>
Formulario HTML
<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>
Código PHP
// 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.
<?php
if (isset($_POST['submit'])) {
$resultado = [
'error' => false,
'mensaje' => 'Usuario agregado con éxito'
];
try {
$dsn = 'mysql:host=' . $config['db']['host'] . ';dbname='
. $config['db']['name'];
$conexion = new PDO($dsn, $config['db']['user'],
$config['db']['pass'], $config['db']['options']);
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
$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 = [
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'],
);
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute($alumno);
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
?>
<?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:
Ataques XSS
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'
];
try {
$alumno = array(
"nombre" => $_POST['nombre'],
"apellido" => $_POST['apellido'],
"email" => $_POST['email'],
"edad" => $_POST['edad'],
);
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute($alumno);
} catch(PDOException $error) {
$resultado['error'] = true;
$resultado['mensaje'] = $error->getMessage();
}
}
?>
<?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>
Código 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']);
} 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.
$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']);
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
$alumnos = $sentencia->fetchAll();
} catch(PDOException $error) {
$error= $error->getMessage();
}
?>
<?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>
Tabla HTML
$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']);
$sentencia = $conexion->prepare($consultaSQL);
$sentencia->execute();
$alumnos = $sentencia->fetchAll();
} catch(PDOException $error) {
$error= $error->getMessage();
}
?>
<?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>
Búsqueda
<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">
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.
Acciones
<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.
$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();
}
<?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>
$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'];
$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
<?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.
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']);
} 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']
];
$consulta = $conexion->prepare($consultaSQL);
$consulta->execute($alumno);
Y con esto ya habremos actualizado los datos del alumno.
$resultado = [
'error' => false,
'mensaje' => ''
];
if (!isset($_GET['id'])) {
$resultado['error'] = true;
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']
];
$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
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>
Código PHP
<?php
include 'funciones.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
<?php
include 'funciones.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();
}
?>
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.
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.
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.