Base de Datos en PHP con PDO
CRUD interactivo (Crear, Leer, Eliminar) con consultas preparadas
🎯 Demo en Vivo (tabla simulada para no requerir tu propia BD)
Añadir producto
| ID | Nombre | Precio | |
|---|---|---|---|
| 1 | Ratón inalámbrico | 19.99 € | |
| 2 | Monitor 24" | 129.00 € |
📖 El mismo CRUD con PDO real (MySQL)
Conexión
$pdo = new PDO(
'mysql:host=localhost;dbname=mi_tienda;charset=utf8mb4',
'usuario',
'contraseña',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
📝 INSERT con consulta preparada
$stmt = $pdo->prepare(
"INSERT INTO productos (nombre, precio) VALUES (:nombre, :precio)"
);
$stmt->execute([
'nombre' => $_POST['nombre'],
'precio' => $_POST['precio']
]);
💡 Concepto: Consultas preparadas
Los marcadores :nombre y :precio se envían por separado del SQL. Así, aunque el usuario escriba algo como '; DROP TABLE productos; --, PDO lo trata como un simple texto, no como código SQL — esto evita la inyección SQL.
📝 SELECT (leer todos)
$stmt = $pdo->query("SELECT id, nombre, precio FROM productos");
$productos = $stmt->fetchAll(PDO::FETCH_ASSOC);
📝 DELETE con parámetro
$stmt = $pdo->prepare("DELETE FROM productos WHERE id = :id");
$stmt->execute(['id' => $_POST['id']]);
🎯 Conceptos Clave
PDO
- Capa única para MySQL, SQLite, PostgreSQL…
- Lanza excepciones con
ERRMODE_EXCEPTION
Prepared statements
- Separan el SQL de los datos del usuario
- Previenen inyección SQL
fetchAll / execute
fetchAll(PDO::FETCH_ASSOC)para arrays asociativosexecute([...])para pasar los parámetros
💪 Ejercicio Práctico
Completa el CRUD
- Añade una acción "editar" que actualice nombre y precio con un
UPDATE ... WHERE id = :id. - Envuelve la conexión en un
try/catchcapturandoPDOException. - Añade paginación con
LIMIT :inicio, :cantidad.
Solución 1
$stmt = $pdo->prepare(
"UPDATE productos SET nombre = :nombre, precio = :precio WHERE id = :id"
);
$stmt->execute(['nombre' => $nombre, 'precio' => $precio, 'id' => $id]);
Solución 2
try {
$pdo = new PDO($dsn, $usuario, $clave, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
} catch (PDOException $e) {
die(t('Error de conexión: ') . $e->getMessage());
}
Solución 3
$stmt = $pdo->prepare("SELECT * FROM productos LIMIT :inicio, :cantidad");
$stmt->bindValue(':inicio', $inicio, PDO::PARAM_INT);
$stmt->bindValue(':cantidad', $cantidad, PDO::PARAM_INT);
$stmt->execute();