En la guía anterior conectamos PHP con MySQL utilizando PDO y aprendimos a leer datos con SELECT.
Ahora vamos a avanzar con las operaciones que permiten crear, modificar y eliminar registros. Es decir, vamos a empezar a trabajar con la parte operativa de una aplicación real.
¿Querés profundizar en la parte SQL?
En esta guía vamos a utilizar INSERT, UPDATE, DELETE y WHERE. La teoría completa de estas sentencias está desarrollada en nuestra ruta de aprendizaje SQL / MySQL.
Las tres operaciones que veremos
- INSERT: crear registros nuevos;
- UPDATE: modificar registros existentes;
- DELETE: eliminar registros.
Las tres operaciones se realizarán con consultas preparadas mediante PDO.
Tabla de ejemplo
Seguimos trabajando con la tabla usuarios:
usuarios
-------------------------
id
nombre
email
edad
Insertar un usuario
La consulta SQL básica sería:
INSERT INTO usuarios (nombre, email, edad) VALUES ('Ana', 'ana@email.com', 25);
Pero desde PHP no debemos concatenar directamente valores recibidos del usuario.
Utilizamos placeholders:
$sql =
'INSERT INTO usuarios
(nombre, email, edad)
VALUES
(:nombre, :email, :edad)';
$stmt = $pdo->prepare($sql);
Ejecutar el INSERT
$stmt->execute([ 'nombre' => $nombre, 'email' => $email, 'edad' => $edad ]);
Formulario de alta
<form method="post"> <label for="nombre">Nombre:</label> <input type="text" id="nombre" name="nombre" > <br><br> <label for="email">Email:</label> <input type="email" id="email" name="email" > <br><br> <label for="edad">Edad:</label> <input type="number" id="edad" name="edad" > <br><br> <button type="submit"> Guardar </button> </form>
Procesar el formulario
<?php require 'conexion.php'; $errores = []; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $nombre = trim($_POST['nombre'] ?? ''); $email = trim($_POST['email'] ?? ''); $edad = trim($_POST['edad'] ?? ''); if ($nombre === '') { $errores[] = 'El nombre es obligatorio'; } if (!filter_var( $email, FILTER_VALIDATE_EMAIL )) { $errores[] = 'El email no es válido'; } if ($edad === '' || !is_numeric($edad)) { $errores[] = 'La edad no es válida'; } if (empty($errores)) { $sql = 'INSERT INTO usuarios (nombre, email, edad) VALUES (:nombre, :email, :edad)'; $stmt = $pdo->prepare($sql); $stmt->execute([ 'nombre' => $nombre, 'email' => $email, 'edad' => $edad ]); echo 'Usuario guardado correctamente'; } }
Recuperar el ID insertado
Si la tabla utiliza una clave autoincremental, PDO puede devolver el último ID generado:
$id = $pdo->lastInsertId(); echo 'Nuevo usuario: ' . $id;
Esto puede ser útil si después queremos redirigir al detalle del registro recién creado.
Modificar un registro con UPDATE
Supongamos que queremos cambiar nombre y email de un usuario.
$sql =
'UPDATE usuarios
SET nombre = :nombre,
email = :email,
edad = :edad
WHERE id = :id';
$stmt = $pdo->prepare($sql);
$stmt->execute([
'nombre' => $nombre,
'email' => $email,
'edad' => $edad,
'id' => $id
]);
¿Querés profundizar en la parte SQL?
En esta guía vamos a utilizar INSERT, UPDATE, DELETE y WHERE. La teoría completa de estas sentencias está desarrollada en nuestra ruta de aprendizaje SQL / MySQL.
¿Por qué WHERE es fundamental en UPDATE?
La cláusula WHERE indica qué registro debe modificarse.
Una consulta como:
UPDATE usuarios SET nombre = 'Ana';
podría modificar todos los registros de la tabla.
Por eso, antes de ejecutar un UPDATE, debemos revisar con especial cuidado la condición utilizada.
Editar un usuario: primer paso
Normalmente recibimos el ID mediante GET:
editar.php?id=5
Lo validamos:
$id = filter_input( INPUT_GET, 'id', FILTER_VALIDATE_INT ); if ($id === false || $id === null) { exit('ID no válido'); }
Buscar el usuario antes de editar
$sql =
'SELECT id, nombre, email, edad
FROM usuarios
WHERE id = :id';
$stmt = $pdo->prepare($sql);
$stmt->execute([
'id' => $id
]);
$usuario = $stmt->fetch();
if (!$usuario) {
exit('Usuario no encontrado');
}
Precargar el formulario
<form method="post"> <input type="text" name="nombre" value="<?php echo htmlspecialchars( $usuario['nombre'], ENT_QUOTES, 'UTF-8' ); ?>" > <input type="email" name="email" value="<?php echo htmlspecialchars( $usuario['email'], ENT_QUOTES, 'UTF-8' ); ?>" > <input type="number" name="edad" value="<?php echo htmlspecialchars( $usuario['edad'], ENT_QUOTES, 'UTF-8' ); ?>" > <button type="submit"> Guardar cambios </button> </form>
Procesar la edición
if ($_SERVER['REQUEST_METHOD'] === 'POST') { $nombre = trim($_POST['nombre'] ?? ''); $email = trim($_POST['email'] ?? ''); $edad = trim($_POST['edad'] ?? ''); if ($nombre === '') { $errores[] = 'El nombre es obligatorio'; } if (!filter_var( $email, FILTER_VALIDATE_EMAIL )) { $errores[] = 'El email no es válido'; } if (empty($errores)) { $sql = 'UPDATE usuarios SET nombre = :nombre, email = :email, edad = :edad WHERE id = :id'; $stmt = $pdo->prepare($sql); $stmt->execute([ 'nombre' => $nombre, 'email' => $email, 'edad' => $edad, 'id' => $id ]); echo 'Usuario actualizado'; } }
Eliminar un registro
La operación DELETE también debe incluir una condición:
DELETE FROM usuarios WHERE id = 5;
Desde PHP:
$sql =
'DELETE FROM usuarios
WHERE id = :id';
$stmt = $pdo->prepare($sql);
$stmt->execute([
'id' => $id
]);
No eliminar mediante enlaces GET
No conviene hacer algo como:
<a href="eliminar.php?id=5"> Eliminar </a>
Un enlace representa naturalmente una navegación. Para una acción destructiva es preferible utilizar un formulario con POST.
Formulario para eliminar
<form
method="post"
action="eliminar.php"
>
<input
type="hidden"
name="id"
value="5"
>
<button type="submit">
Eliminar
</button>
</form>
Procesar la eliminación
<?php require 'conexion.php'; if ($_SERVER['REQUEST_METHOD'] !== 'POST') { exit('Método no permitido'); } $id = filter_input( INPUT_POST, 'id', FILTER_VALIDATE_INT ); if ($id === false || $id === null) { exit('ID no válido'); } $sql = 'DELETE FROM usuarios WHERE id = :id'; $stmt = $pdo->prepare($sql); $stmt->execute([ 'id' => $id ]); echo 'Usuario eliminado';
Validar que el registro exista
Antes de modificar o eliminar, podemos comprobar que el registro exista.
$stmt = $pdo->prepare( 'SELECT id FROM usuarios WHERE id = :id' ); $stmt->execute([ 'id' => $id ]); if (!$stmt->fetch()) { exit('Usuario no encontrado'); }
Estructura sencilla de archivos
usuarios/ │ ├── conexion.php ├── index.php ├── crear.php ├── editar.php └── eliminar.php
Por ahora es una estructura simple y didáctica. Más adelante veremos cómo organizar aplicaciones más grandes.
index.php
Puede mostrar el listado de usuarios y los botones de acción:
<?php foreach ($usuarios as $usuario): ?> <p> <?php echo htmlspecialchars( $usuario['nombre'], ENT_QUOTES, 'UTF-8' ); ?> <a href="editar.php?id=<?php echo $usuario['id']; ?>"> Editar </a> <form method="post" action="eliminar.php" style="display:inline" > <input type="hidden" name="id" value="<?php echo $usuario['id']; ?>" > <button type="submit"> Eliminar </button> </form> </p> <?php endforeach; ?>
Mensajes después de una operación
En una aplicación real suele ser más cómodo redirigir después de insertar, actualizar o eliminar.
header(
'Location: index.php?mensaje=creado'
);
exit;
Luego podemos mostrar un mensaje:
$mensaje = $_GET['mensaje'] ?? ''; if ($mensaje === 'creado') { echo 'Usuario creado correctamente'; }
Por qué redirigir después de POST
Después de procesar un formulario, una redirección evita que el navegador intente repetir la operación si el usuario actualiza la página.
Este patrón se conoce habitualmente como:
POST ↓ procesamiento ↓ redirect ↓ GET
También se lo conoce como Post/Redirect/Get.
Una mejora importante: confirmar eliminaciones
Podemos pedir confirmación en el navegador:
<form
method="post"
action="eliminar.php"
onsubmit="return confirm(
'¿Seguro que querés eliminar este usuario?'
);"
>
Esto mejora la experiencia, aunque la autorización real de la operación siempre debe controlarse también en el servidor.
Consultas preparadas en todas las operaciones
En las tres operaciones mantenemos el mismo patrón:
$sql = '... :valor ...'; $stmt = $pdo->prepare($sql); $stmt->execute([ 'valor' => $dato ]);
Esto evita construir SQL concatenando datos externos.
Errores comunes
- concatenar valores del usuario dentro de SQL;
- olvidar el
WHEREen un UPDATE; - olvidar el
WHEREen un DELETE; - usar GET para ejecutar una eliminación;
- no validar IDs;
- no comprobar si el registro existe;
- no validar el formulario antes de guardar;
- no utilizar consultas preparadas;
- actualizar o eliminar registros sin verificar permisos;
- repetir un POST accidentalmente al recargar la página.
Buenas prácticas
- validar siempre los datos antes de escribir en la base;
- utilizar
prepare()yexecute(); - validar IDs con filtros apropiados;
- comprobar la existencia del registro;
- usar POST para acciones que modifican datos;
- redireccionar después de operaciones exitosas;
- escapar datos al mostrarlos en HTML;
- controlar permisos antes de modificar o eliminar;
- revisar cuidadosamente las condiciones de UPDATE y DELETE.
Ejercicios
- crear un formulario para insertar usuarios;
- validar nombre, email y edad;
- guardar el usuario mediante PDO;
- mostrar el ID generado con
lastInsertId(); - crear una página de edición;
- precargar el formulario con los datos actuales;
- actualizar mediante una consulta preparada;
- crear un formulario POST para eliminar;
- validar el ID recibido;
- mostrar mensajes después de cada operación;
- aplicar Post/Redirect/Get;
- agregar confirmación antes de eliminar.
Qué aprendimos
- cómo insertar registros con PDO;
- cómo recuperar el ID insertado;
- cómo modificar registros con UPDATE;
- cómo precargar un formulario;
- cómo eliminar registros;
- por qué debemos validar IDs;
- por qué las operaciones destructivas no deberían ejecutarse por GET;
- cómo combinar formularios, PDO y consultas preparadas;
- qué es Post/Redirect/Get.
Continuá aprendiendo SQL / MySQL
Para profundizar en INSERT, UPDATE, DELETE, restricciones, relaciones y demás conceptos propios de la base de datos, podés seguir nuestra ruta completa:
¿Qué sigue?
En la próxima guía vamos a integrar todo lo aprendido en un CRUD completo con PHP, MySQL y PDO: listado, alta, edición, eliminación y búsqueda dentro de una pequeña aplicación funcional.
¿Te sirvió esta guía? ☕
Si este contenido te ayudó y querés apoyar a Club Programador, podés colaborar mediante:
Descubre más desde Club Programador
Suscríbete y recibe las últimas entradas en tu correo electrónico.