Saltar a contenido

PHP Data Objects :: PDO

PDO proporciona una capa de abstracción de acceso a datos, lo que significa que, independientemente de la base de datos que se esté utilizando, se usan las mismas funciones para realizar consultas y obtener datos.

De la misma manera que hemos visto con MySQLi, PHP Data Objects (o PDO) es un driver de PHP que se utiliza para trabajar bajo una interfaz de objetos con la base de datos. A día de hoy es lo que más se utiliza para manejar información desde una base de datos, ya sea relacional o no relacional.

De igual manera que pasaba con los objetos en PHP nativos, en la interfaz de MySQL la cosa cambia la hora de conectarnos con una base de datos, de manera que ahora necesitamos instanciar la clase PDO:

<?php

$conexion = new PDO('mysql:host=localhost; dbname=dwes', 'dwes', 'abc123');

Además, con PDO podemos usar las excepciones con try catch para gestionar los errores que se produzcan en nuestra aplicación. Para ello, como hacíamos antes, debemos encapsular el código entre bloques try / catch:

<?php

$dsn = 'mysql:dbname=prueba;host=127.0.0.1';
$usuario = 'usuario';
$contraseña = 'contraseña';

try {
    $mbd = new PDO($dsn, $usuario, $contraseña);
    $mbd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Falló la conexión: ' . $e->getMessage();
}
En primer lugar, creamos la conexión con la base de datos a través del constructor PDO pasándole la información de la base de datos.

En segundo lugar, establecemos los parámetros para manejar las excepciones, en este caso hemos utilizado:

  • PDO::ATTR_ERRMODE indicándole a PHP que queremos un reporte de errores.
  • PDO::ERRMODE_EXCEPTION con este atributo obligamos a que lance excepciones, además de ser la opción más humana y legible que hay a la hora de controlar errores.

PDOException

Cualquier error que se lance a través de PDO, el sistema lanzará una PDOException.

Fichero de configuración de la BD

De la misma manera que creamos nuestro archivo de funciones funciones-php y albergamos todas las funciones que se usan de manera global en la aplicación, podemos establecer un archivo de constantes donde definamos los parámetros de conexión con la base de datos (en nuestro caso lo vamos a colocar dentro de la carpeta config)

database.inc.php
<?php

constDSN = "mysql:host=localhost;dbname=dwes";
constUSUARIO = "dwes";
constPASSWORD = "abc123";

/* Añade este archivo a .gitignore para que no se suba a Git */

Este archivo contiene información muy sensible así que no es recomendable que subas este archivo a Git (más bien es un agujero de seguridad).

Sentencias preparadas

Se trata de sentencias que se establecen como si fueran plantillas de la SQL que vamos a lanzar, aceptando parámetros que son establecidos a posteriori de la declaración de la sentencia preparada.

Las sentencias preparadas evitan la inyección de SQL (SQL Injection) y mejoran el rendimiento de nuestras aplicaciones o páginas web.

<?php

$sql = "INSERT INTO clientes VALUES (?, ?, ?, ?)";

Cada interrogante es un parámetro que estableceremos después, unas cuantas líneas más abajo.

Una vez tenemos la plantilla de nuestra consulta, debemos seguir con la preparación junto con 3 métodos más de PHP para su completa ejecución:

  • prepare: prepara la sentencia antes de ser ejecutada
  • bind: el tipo de unión (bind) de dato que puede ser mediante ? o :parametro
  • execute se ejecuta la consulta uniendo la plantilla con las variables o parámetros que hemos establecido.

Ejemplo parámetros

<?php
include "config/database.inc.php";

$conexion = null;

try { 
    $cantidad = $_GET["cantidad"];

    $conexion = new PDO(DSN, USUARIO, PASSWORD);
    $conexion -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "DELETE FROM stock WHERE unidades = ?";
    $sentencia = $conexion -> prepare($sql);

    $isOk = $sentencia -> execute([$cantidad]);
    $cantidadAfectada = $sentencia -> rowCount();

    echo $cantidadAfectada;
} catch (PDOException $e) {
    echo $e -> getMessage();
}

$conexion = null

Ejemplo bindParam

Muy parecido a utilizar parámetros pero esta vez la variable está dentro de la sentencia SQL, en este caso la hemos llamado :cant. Esta forma facilita la lectura de las consultas y la asignación de los valores a los parámetros:

<?php
include "config/database.inc.php";

$conexion=null;

try {
    $cantidad = $_GET["cantidad"] ?? 0;

    $conexion = new PDO(DSN, USUARIO, PASSWORD);
    $conexion -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "DELETE FROM stock WHERE unidades = :cant";

    $sentencia = $conexion -> prepare($sql);
    $sentencia -> bindParam(":cant", $cantidad);

    $isOk = $sentencia -> execute();

    $cantidadAfectada = $sentencia -> rowCount();

    echo $cantidadAfectada;
} catch (PDOException $e) {
    echo $e -> getMessage();
}

$conexion = null;

bindParam VS bindValue

Utilizaremos bindValue() cuando tengamos que insertar datos sólo una vez, en cambio, deberemos usar bindParam() cuando tengamos que pasar datos múltiples, como por ejemplo, un array.

<?php
// se asignan nombre a los parámetros
$sql = "DELETE FROM stock WHERE unidades = :cant";
$sentencia = $conexion -> prepare($sql);

// bindParam enlaza por referencia
$cantidad = 0;

$sentencia -> bindParam(":cant", $cantidad);
$cantidad = 1;

// se eliminan con cant = 1
$isOk = $sentencia -> execute();

// bindValue enlaza por valor
$cantidad = 0;

$sentencia -> bindValue(":cant", $cantidad);
$cantidad = 1;

// se eliminan con cant = 0
$isOk = $sentencia->execute();

Para más información y uso de las variables PDO consulta el manual de PHP.

Actividades

  • 📝 AC 614. (RA6 / CE6b CE6c/ IC1 / 3p) - Vuelve a realizar las actividades AC 610-611, cambiando todo el uso de MySQLi por PDO.

  • 🏹 RE 615. (RA6 / CE6b CE6c CE6d CE6e CE6f CE6g / IC2 / 15p) - Esta actividad marca el inicio del desarrollo del Reto 03 y consiste en diseñar y construir la base de datos inicial para el proyecto de tienda online. Se espera que se defina la estructura relacional del sistema y que, una vez creada la base de datos, realice operaciones básicas de consulta y manipulación usando sentencias SQL desde PHP con PDO, aplicando buenas prácticas de seguridad y estructura.

    Durante esta actividad se deberá:

    • Diseñar el esquema relacional de la base de datos (productos, usuarios, roles, etc.).
    • Crear el script SQL de creación de la base de datos y ejecutarlo correctamente.
    • Establecer relaciones entre tablas según las necesidades del futuro sistema.
    • Insertar algunos registros de prueba manualmente o desde un script.
    • Conectar a la base de datos desde un archivo PHP utilizando PDO.
    • Realizar consultas básicas desde PHP.
    • Aplicar sentencias preparadas para evitar inyecciones SQL.
    • Verificar que la base de datos y el acceso desde PHP funcionan correctamente.

    Esta base de datos se reutilizará y adaptará posteriormente en Laravel, por lo que su correcto diseño e implementación es clave para las siguientes fases del reto.