Content-Type: application/x-php Conectar PHP con MySQL usando PDO: conexión, CRUD y buenas prácticas | Línea de Código

PHP

Conectar PHP con MySQL usando PDO: conexión, CRUD y buenas prácticas

Aprende a conectar PHP con MySQL mediante PDO con un ejemplo completo: desde la cadena de conexión hasta un CRUD funcional con consultas preparadas.

Tipo: Guía práctica Lectura: 3 min Actualizado: 2026-07-05
Conectar PHP con MySQL usando PDO de forma segura.

Conexión segura

Por qué usar PDO en lugar de mysqli

PDO (PHP Data Objects) es la capa de abstracción recomendada para conectar PHP con bases de datos. A diferencia de mysqli, PDO permite cambiar de motor sin reescribir el código: MySQL, PostgreSQL, SQLite y otros usan la misma interfaz.

La ventaja principal son las consultas preparadas: separan el SQL de los datos y evitan la inyección SQL de raíz. Con PDO también puedes elegir entre excepciones, errores silenciosos o arrays asociativos sin cambiar la lógica de negocio.

Cadena de conexión y configuración básica

<?php

declare(strict_types=1);

function conectar(): PDO
{
    $host = 'localhost';
    $dbname = 'mi_aplicacion';
    $username = 'usuario';
    $password = 'contraseña';
    $charset = 'utf8mb4';

    $dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";

    $opciones = [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ];

    return new PDO($dsn, $username, $password, $opciones);
}

La cadena DSN incluye el driver (`mysql:`), el host, el nombre de la base de datos y el charset. `utf8mb4` es obligatorio si usas emojis o caracteres especiales. Las opciones configuran PDO para que lance excepciones, devuelva arrays asociativos y use consultas preparadas reales en lugar de emuladas.

PDO vs mysqli: diferencias clave

Característica PDO mysqli
Soporte de motores MySQL, PostgreSQL, SQLite, Oracle, etc. Solo MySQL
Consultas preparadas Sí, con parámetros con nombre o posicionales Sí, con marcadores de posición
Modo de errores Excepciones, warnings, silencioso Modo report o excepciones
Fetch modes ASSOC, OBJ, BOTH, CLASS, LAZY, etc. ASSOC, OBJ, BOTH, NUM
API orientada a objetos Sí, completa Sí, con versión procedural
Portabilidad Alta: cambias el DSN y funciona Baja: solo MySQL/MariaDB

Para proyectos nuevos o migraciones futuras, PDO es la opción recomendada por PHP-FIG y la documentación oficial.

Consultas preparadas con parámetros con nombre

<?php

function obtenerUsuarioPorEmail(PDO $pdo, string $email): array|false
{
    $sql = 'SELECT id, nombre, email FROM usuarios WHERE email = :email';
    $stmt = $pdo->prepare($sql);
    $stmt->execute([':email' => $email]);
    return $stmt->fetch();
}

function insertarUsuario(PDO $pdo, string $nombre, string $email): int
{
    $sql = 'INSERT INTO usuarios (nombre, email) VALUES (:nombre, :email)';
    $stmt = $pdo->prepare($sql);
    $stmt->execute([':nombre' => $nombre, ':email' => $email]);
    return (int) $pdo->lastInsertId();
}

Los parámetros con nombre (`:email`, `:nombre`) hacen el código más legible que los marcadores posicionales (`?`). La inyección SQL queda descartada porque los valores nunca se concatenan con el SQL. Cada valor se envía por separado al motor.

CRUD completo con PDO

<?php

class UsuarioRepositorio
{
    public function __construct(private PDO $pdo) {}

    public function listar(): array
    {
        $stmt = $this->pdo->query('SELECT id, nombre, email FROM usuarios ORDER BY id');
        return $stmt->fetchAll();
    }

    public function obtener(int $id): array|false
    {
        $sql = 'SELECT id, nombre, email FROM usuarios WHERE id = :id';
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':id' => $id]);
        return $stmt->fetch();
    }

    public function crear(string $nombre, string $email): int
    {
        $sql = 'INSERT INTO usuarios (nombre, email) VALUES (:nombre, :email)';
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':nombre' => $nombre, ':email' => $email]);
        return (int) $this->pdo->lastInsertId();
    }

    public function actualizar(int $id, string $nombre, string $email): bool
    {
        $sql = 'UPDATE usuarios SET nombre = :nombre, email = :email WHERE id = :id';
        $stmt = $this->pdo->prepare($sql);
        return $stmt->execute([':id' => $id, ':nombre' => $nombre, ':email' => $email]);
    }

    public function eliminar(int $id): bool
    {
        $sql = 'DELETE FROM usuarios WHERE id = :id';
        $stmt = $this->pdo->prepare($sql);
        return $stmt->execute([':id' => $id]);
    }
}

Este CRUD encapsula cada operación en un método independiente. El constructor recibe la conexión PDO por inyección, lo que facilita pruebas y reutilización. Cada método prepara la consulta, ejecuta con los parámetros y devuelve el resultado con el tipo correcto.

Pasos para integrar PDO en tu proyecto

  1. Confirma que PHP tiene el driver pdo_mysql instalado con php -m | findstr pdo.
  2. Crea una función o clase que devuelva una instancia de PDO con las opciones recomendadas.
  3. Define el DSN con utf8mb4 y el modo de error ERRORMODE_EXCEPTION.
  4. Usa consultas preparadas con parámetros con nombre en todas las operaciones con datos externos.
  5. Captura las excepciones PDOException para mostrar errores sin exponer detalles internos.
  6. Cierra la conexión automáticamente: PDO no necesita cierre manual, pero asignar null libera el recurso.

Manejo de errores con excepciones

<?php

try {
    $pdo = conectar();
    $repo = new UsuarioRepositorio($pdo);
    $usuarios = $repo->listar();
} catch (PDOException $e) {
    error_log('Error de base de datos: ' . $e->getMessage());
    http_response_code(500);
    echo 'Error interno. Intenta de nuevo más tarde.';
    exit;
}

Configurar `ERRMODE_EXCEPTION` hace que PDO lance `PDOException` en cualquier fallo: conexión rechazada, SQL mal formado, restricciones de clave duplicada. Captura la excepción en un bloque try-catch, registra el error técnico en el log y muestra un mensaje genérico al usuario. Nunca expongas el mensaje real de la excepción en producción.

Preguntas frecuentes

¿Qué necesito instalar para usar PDO con MySQL?

PHP debe tener la extensión pdo_mysql habilitada. En Ubuntu: sudo apt install php-mysql. En Windows: descomenta extension=pdo_mysql en php.ini. Verifica con php -m.

¿PDO es más lento que mysqli?

La diferencia es mínima en aplicaciones reales. La seguridad que aportan las consultas preparadas compensa cualquier micro-optimización.

¿Debo cerrar la conexión PDO manualmente?

No es obligatorio. PDO cierra la conexión al finalizar el script. Si necesitas liberar recursos antes, asigna null a la variable: $pdo = null.

¿Puedo usar PDO con consultas sin preparar?

Puedes usar query() para consultas sin parámetros externos. Para cualquier valor que venga del usuario, usa prepare() con execute().

Fuentes consultadas

Fuentes y referencias

Consulta referencias útiles para ampliar o contrastar esta guía.

Marcos Vidal

Autora de la guia

Marcos Vidal

Editor de guías de programación práctica

Prepara ejemplos y explicaciones de PHP, Java y JavaScript para que cada snippet se pueda probar, adaptar y mantener con menos dudas.

Credenciales: Experiencia editorial en tutoriales técnicos, revisión de snippets y documentación para estudiantes de programación.

Experiencia: Trabaja con ejemplos mínimos, pruebas manuales y listas de comprobación para reducir errores de integración.

Actualizado: 2026-07-05 Politica editorial Correcciones

Por que confiar

Contrastamos fuentes oficiales, actualizamos piezas clave y priorizamos estructura, contexto y enlazado interno por encima del relleno.

Compartir

Guarda o comparte esta guia con el enlace limpio.