PHP · MySQL · PDO · CRUD

PHP con MySQL: PDO, CRUD y consultas seguras paso a paso

PHP y MySQL permiten construir aplicaciones web capaces de guardar, consultar, modificar y eliminar información de forma persistente. La forma correcta de aprender esta combinación no consiste en concatenar consultas SQL dentro de archivos PHP: necesitas comprender PDO, consultas preparadas, relaciones, transacciones, validación, errores y una estructura de aplicación mantenible.

PDO CRUD · SQL · Relaciones Seguridad
Respuesta rápida

¿Cómo se conecta PHP con MySQL?

Una forma moderna de conectar PHP con MySQL es mediante PDO.

PDO permite abrir una conexión, preparar consultas SQL, enviar parámetros, ejecutar instrucciones y recuperar resultados.

Para trabajar correctamente deberías aprender al menos: SELECT, INSERT, UPDATE, DELETE, consultas preparadas, transacciones, relaciones e índices.

Y desde PHP necesitas comprender validación, excepciones, separación de responsabilidades y seguridad.

Publicidad
Mapa de aprendizaje

PHP y MySQL implican mucho más que abrir una conexión

01

PDO

Conexión, consultas y manejo de errores.

02

CRUD

Crear, consultar, modificar y eliminar datos.

03

Seguridad

Parámetros, validación y consultas preparadas.

04

Relaciones

Conectar usuarios, pedidos, productos y otras entidades.

05

Transacciones

Ejecutar varias operaciones como una unidad.

06

Rendimiento

Índices, paginación y consultas eficientes.

Publicidad
Persistencia

MySQL permite que los datos sobrevivan después de terminar una solicitud PHP

Una variable PHP existe durante la ejecución de un programa.

Cuando termina esa solicitud, esa variable no se convierte automáticamente en información permanente.

Una base de datos resuelve otro problema

Permite almacenar usuarios, productos, publicaciones, pedidos, mensajes, configuraciones y muchas otras entidades.

PHP puede encargarse de las reglas de la aplicación mientras MySQL mantiene los datos.

PHP y MySQL cumplen responsabilidades diferentes.

PHP ejecuta lógica. MySQL organiza y consulta información persistente.

Antes de PDO

Aprende SQL además de aprender PHP

Un error habitual es aprender únicamente cómo ejecutar consultas desde PHP.

Eso puede funcionar mientras los ejemplos sean sencillos, pero limita rápidamente tu capacidad para diseñar sistemas.

SELECT

Recupera información.

INSERT

Crea nuevos registros.

UPDATE

Modifica información existente.

DELETE

Elimina registros.

JOIN

Permite combinar información relacionada de varias tablas.

PHP ejecuta estas consultas, pero SQL sigue siendo un lenguaje que necesitas comprender por separado.

Publicidad
Base de datos inicial

Empecemos con una tabla de usuarios

SQL MySQL
CREATE TABLE usuarios (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(120) NOT NULL,
    email VARCHAR(190) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    activo TINYINT(1) NOT NULL DEFAULT 1,
    creado_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

id identifica cada registro

Una clave primaria proporciona una referencia única para cada usuario.

email tiene una restricción UNIQUE

Eso ayuda a impedir que se almacenen dos usuarios con el mismo email.

No guardamos la contraseña como texto

Guardamos un hash producido desde PHP mediante funciones diseñadas específicamente para contraseñas.

PDO

Crear una conexión PDO con MySQL

conexion.php PHP
<?php

$dsn = 'mysql:host=localhost;dbname=ciborg;charset=utf8mb4';

$pdo = new PDO(
    $dsn,
    $usuarioDb,
    $passwordDb,
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ]
);

utf8mb4

Permite trabajar correctamente con un conjunto amplio de caracteres.

ERRMODE_EXCEPTION

Hace que determinados errores de base de datos generen excepciones, facilitando su manejo.

FETCH_ASSOC

Hace que los resultados se recuperen por defecto como arrays asociativos.

No publiques credenciales reales dentro de código visible o repositorios públicos.

Configuración, secretos y credenciales deberían mantenerse fuera de archivos expuestos públicamente.

Manejo de errores

La aplicación debe manejar errores sin revelar información sensible

Durante desarrollo, un error detallado puede ayudarte a encontrar el problema.

En producción, mostrar credenciales, rutas internas o consultas completas puede ser peligroso.

Excepciones PHP
<?php

try {

    $pdo = new PDO(
        $dsn,
        $usuarioDb,
        $passwordDb,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
        ]
    );

} catch (PDOException $e) {

    error_log($e->getMessage());

    exit(
        'No fue posible conectar con la base de datos.'
    );
}

El usuario recibe un mensaje controlado, mientras el detalle técnico puede registrarse internamente.

Publicidad
CRUD · Create

INSERT: guardar un registro utilizando una consulta preparada

INSERT PDO
<?php

$sql = "
    INSERT INTO usuarios (
        nombre,
        email,
        password_hash
    )
    VALUES (
        :nombre,
        :email,
        :password_hash
    )
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'nombre' => $nombre,
    'email' => $email,
    'password_hash' => $passwordHash,
]);

Los parámetros van separados de la consulta

Los valores no se concatenan directamente dentro del SQL.

La contraseña debe convertirse primero en hash

password_hash PHP
<?php

$passwordHash = password_hash(
    $password,
    PASSWORD_DEFAULT
);

Nunca necesitas recuperar la contraseña original desde la base de datos.

CRUD · Read

SELECT: recuperar información

SELECT PDO
<?php

$sql = "
    SELECT
        id,
        nombre,
        email,
        activo,
        creado_en
    FROM usuarios
    ORDER BY creado_en DESC
";

$stmt = $pdo->query($sql);

$usuarios = $stmt->fetchAll();

Después puedes recorrer los resultados

Resultados PHP
<?php foreach ($usuarios as $usuario): ?>

    <p>
        <?php echo htmlspecialchars(
            $usuario['nombre'],
            ENT_QUOTES,
            'UTF-8'
        ); ?>
    </p>

<?php endforeach; ?>
Consultas preparadas protegen SQL; escapar la salida protege otro contexto.

Son problemas diferentes y ambos deben considerarse.

Consultas parametrizadas

Buscar un usuario por email

WHERE PDO
<?php

$sql = "
    SELECT
        id,
        nombre,
        email,
        password_hash,
        activo
    FROM usuarios
    WHERE email = :email
    LIMIT 1
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'email' => $email
]);

$usuario = $stmt->fetch();

Este patrón aparece constantemente en login, perfiles, búsquedas y comprobaciones de existencia.

CRUD · Update

UPDATE: modificar información existente

UPDATE PDO
<?php

$sql = "
    UPDATE usuarios
    SET
        nombre = :nombre,
        email = :email
    WHERE id = :id
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'nombre' => $nombre,
    'email' => $email,
    'id' => $id,
]);

WHERE es fundamental

Una actualización sin una condición adecuada puede afectar muchos registros.

Antes de ejecutar operaciones destructivas, verifica cuidadosamente qué registros deben modificarse.

CRUD · Delete

DELETE: eliminar información de manera controlada

DELETE PDO
<?php

$sql = "
    DELETE FROM usuarios
    WHERE id = :id
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'id' => $id
]);

Técnicamente es sencillo; conceptualmente puede no serlo

En una aplicación real debes decidir qué ocurre con información relacionada.

Por ejemplo: ¿qué ocurre con pedidos, comentarios, archivos o auditorías asociados al usuario?

La estructura de la base de datos importa tanto como la consulta PHP.

Publicidad
Seguridad

No construyas SQL concatenando directamente datos del usuario

Este tipo de código debería evitarse:

Incorrecto SQL
<?php

$sql = "
    SELECT *
    FROM usuarios
    WHERE email = '" . $_POST['email'] . "'
";

La información recibida está entrando directamente en la estructura de la consulta.

Utiliza parámetros

Correcto PDO
<?php

$sql = "
    SELECT *
    FROM usuarios
    WHERE email = :email
";

$stmt = $pdo->prepare($sql);

$stmt->execute([
    'email' => $email
]);
Prepared statements no reemplazan toda la seguridad de la aplicación.

También necesitas validar datos, controlar permisos, proteger formularios y escapar correctamente la salida.

Datos de entrada

Antes de guardar información, valida que tenga sentido

Una consulta preparada evita mezclar datos con SQL, pero no puede saber qué reglas necesita tu negocio.

Email

Debe tener un formato aceptable.

Precio

Puede necesitar ser mayor o igual a cero.

Estado

Puede pertenecer solamente a un conjunto de valores permitidos.

Validación PHP
<?php

$email = filter_input(
    INPUT_POST,
    'email',
    FILTER_VALIDATE_EMAIL
);

if ($email === false || $email === null) {
    exit('Email inválido');
}
Modelo relacional

Las aplicaciones reales suelen tener varias tablas relacionadas

Imagina un ecommerce.

Un usuario puede tener muchos pedidos.

Un pedido puede contener varios productos.

Los productos pueden pertenecer a categorías.

Claves foráneas

SQL Relación
CREATE TABLE pedidos (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    usuario_id BIGINT UNSIGNED NOT NULL,
    total DECIMAL(12,2) NOT NULL,
    estado VARCHAR(50) NOT NULL,
    creado_en DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT fk_pedidos_usuario
        FOREIGN KEY (usuario_id)
        REFERENCES usuarios(id)
);

Ahora cada pedido puede relacionarse con un usuario mediante usuario_id.

JOIN

Combinar información relacionada con JOIN

JOIN MySQL
SELECT
    pedidos.id,
    pedidos.total,
    pedidos.estado,
    usuarios.nombre,
    usuarios.email

FROM pedidos

INNER JOIN usuarios
    ON usuarios.id = pedidos.usuario_id

ORDER BY pedidos.creado_en DESC;

Con una sola consulta podemos obtener información del pedido junto con datos del usuario relacionado.

Aquí SQL empieza a demostrar por qué debe aprenderse de verdad

Las aplicaciones rara vez consisten en una única tabla aislada.

Publicidad
Transacciones

Algunas operaciones deben completarse juntas o no completarse

Imagina una compra.

Necesitas crear un pedido, guardar sus productos y quizás descontar stock.

Si una operación falla en medio, no quieres dejar la base en un estado incoherente.

Transacción PDO
<?php

try {

    $pdo->beginTransaction();

    // 1. Crear pedido.
    // 2. Insertar productos del pedido.
    // 3. Actualizar stock.

    $pdo->commit();

} catch (Throwable $e) {

    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }

    throw $e;
}

commit confirma

Los cambios se guardan como una unidad.

rollBack revierte

Si algo falla, puedes deshacer los cambios realizados dentro de la transacción.

Transacciones son fundamentales cuando varias operaciones dependen entre sí.

Pedidos, pagos, inventario y movimientos financieros son ejemplos típicos.

Rendimiento

No cargues miles de registros cuando solamente necesitas mostrar veinte

En un proyecto pequeño, fetchAll() puede parecer siempre suficiente.

Pero una tabla puede crecer hasta cientos de miles de registros.

Utiliza paginación

LIMIT / OFFSET MySQL
SELECT
    id,
    nombre,
    email

FROM usuarios

ORDER BY id DESC

LIMIT 20
OFFSET 40;

Aquí se solicitan solamente veinte registros, comenzando después de los primeros cuarenta.

Para grandes volúmenes también existen estrategias de paginación basadas en cursores o claves.

Índices

Los índices pueden acelerar búsquedas, pero no deberían añadirse al azar

Si constantemente buscas usuarios por email, tener ese campo correctamente indexado puede mejorar las consultas.

PRIMARY KEY ya crea una estructura útil para id

Las claves principales suelen utilizarse constantemente para localizar registros.

UNIQUE también puede servir como índice

En nuestro ejemplo, email necesita ser único.

Más índices no significa automáticamente más velocidad

También tienen coste de almacenamiento y mantenimiento durante escrituras.

Debes diseñarlos según consultas reales.

Consultas innecesarias

Evita realizar una consulta adicional por cada fila cuando puedes resolver mejor el problema

Imagina que recuperas cien pedidos.

Después, por cada pedido, haces otra consulta para buscar el usuario.

Terminarías ejecutando una consulta inicial más cien adicionales.

Una combinación bien diseñada puede reducir ese trabajo

JOIN, consultas agrupadas u otras estrategias pueden evitar consultas repetitivas.

El código PHP puede ser limpio y aun así producir SQL ineficiente.

Rendimiento backend también exige comprender qué está haciendo la base de datos.

Publicidad
Arquitectura

No distribuyas consultas SQL por cada archivo HTML de la aplicación

En un CRUD de aprendizaje puede parecer cómodo escribir consultas directamente donde muestras la interfaz.

Cuando el proyecto crece, esa organización se vuelve difícil de mantener.

Separa acceso a datos

Centraliza las operaciones relacionadas con persistencia.

Separa reglas de negocio

Determinar si un usuario puede cancelar un pedido es una regla, no una consulta SQL.

Separa presentación

Generar HTML debería ser una responsabilidad distinta de actualizar una base de datos.

Organización práctica

Una clase puede concentrar las operaciones de usuarios

UsuarioRepository PHP
<?php

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

    public function buscarPorEmail(
        string $email
    ): ?array {

        $sql = "
            SELECT
                id,
                nombre,
                email,
                activo
            FROM usuarios
            WHERE email = :email
            LIMIT 1
        ";

        $stmt = $this->pdo->prepare($sql);

        $stmt->execute([
            'email' => $email
        ]);

        $usuario = $stmt->fetch();

        return $usuario ?: null;
    }
}

Esto no significa que todo proyecto necesite exactamente un patrón Repository.

Lo importante es reconocer que acceso a datos constituye una responsabilidad que puede separarse.

Publicidad
Proyecto práctico

Construye un CRUD completo para aprender PHP con MySQL

1

Crear tabla

Define columnas, tipos y restricciones.

2

Conectar PDO

Configura conexión y errores.

3

Crear registro

Formulario, validación e INSERT.

4

Listar datos

SELECT y paginación.

5

Editar

Buscar por id y ejecutar UPDATE.

6

Eliminar

DELETE con autorización y confirmación.

7

Login

Contraseñas, usuarios y sesiones.

8

Roles

Añade autorización.

9

Relaciones

Añade una segunda entidad relacionada.

10

Refactoriza

Separa datos, lógica y presentación.

Aplicaciones reales

PHP y MySQL pueden convertirse en la base de muchos tipos de sistemas

Directorio

Negocios, categorías, búsquedas y usuarios.

Ecommerce

Productos, clientes, pedidos y stock.

Reservas

Clientes, horarios, disponibilidad y estados.

Cotizaciones

Solicitudes, propuestas, profesionales y estados.

SaaS

Usuarios, planes, consumo y suscripciones.

Panel interno

Administración, reportes y procesos.

¿Qué construir?

PHP puede utilizar MySQL como base para sistemas completos

Explora otros proyectos que puedes desarrollar con el lenguaje.

Qué se puede hacer con PHP →
PHP, MySQL y WordPress

Comprender SQL y bases de datos también mejora tu nivel como desarrollador WordPress

WordPress almacena gran parte de su información en una base de datos relacional.

Sin embargo, cuando desarrollas dentro de WordPress, no deberías saltar automáticamente a consultas SQL personalizadas.

Utiliza primero las APIs disponibles

Posts, usuarios, metadata y opciones disponen de funciones específicas.

Usa $wpdb cuando realmente necesitas acceso SQL

En ese contexto, conceptos como parámetros, índices, relaciones y rendimiento siguen siendo muy importantes.

WordPress

Lleva tus conocimientos PHP y SQL al desarrollo WordPress

Hooks, plugins, $wpdb, REST API y WooCommerce.

PHP para WordPress →
Base de datos + API

PHP puede convertir información de MySQL en una API

Una aplicación móvil, frontend JavaScript u otro sistema no necesita conectarse directamente a MySQL.

PHP puede actuar como capa intermedia.

JSON PHP
<?php

$stmt = $pdo->query(
    "SELECT id, nombre FROM productos"
);

$productos = $stmt->fetchAll();

header(
    'Content-Type: application/json; charset=utf-8'
);

echo json_encode(
    $productos,
    JSON_UNESCAPED_UNICODE
);

En una API real también necesitarías routing, autenticación, autorización, validación, errores y códigos HTTP.

Explorar APIs e integraciones →
Publicidad
Errores frecuentes

Qué evitar al trabajar con PHP y MySQL

Error Concatenar datos en SQL
Prepare
Error Guardar contraseñas en texto plano
Hash
Error Mostrar errores SQL al usuario
Registra
Error Utilizar SELECT * siempre
Selecciona
Error Cargar todos los registros
Pagina
Error No diseñar relaciones
Modela
Error Escribir SQL por toda la interfaz
Separa
Error Copiar consultas de IA sin revisarlas
Verifica
Ruta recomendada

En qué orden aprender PHP con MySQL

1

PHP básico

Variables, funciones, arrays y errores.

2

SQL básico

SELECT, INSERT, UPDATE y DELETE.

3

Diseño de tablas

Tipos, claves y restricciones.

4

PDO

Conexión y consultas.

5

Prepared statements

Parámetros y seguridad SQL.

6

CRUD

Integra PHP, formularios y datos.

7

Relaciones

Claves foráneas y JOIN.

8

Transacciones

Operaciones consistentes.

9

Rendimiento

Índices y paginación.

10

Arquitectura

Separa datos, negocio e interfaz.

Conclusión

Aprender PHP con MySQL significa aprender a diseñar datos, no solo ejecutar consultas

Aprende SQL por separado.

Conecta PHP mediante PDO.

Utiliza consultas preparadas para datos dinámicos.

Practica INSERT, SELECT, UPDATE y DELETE.

Aprende relaciones y JOIN cuando tu aplicación tenga varias entidades.

Utiliza transacciones cuando varias operaciones deban completarse juntas.

Añade índices y paginación cuando los datos comiencen a crecer.

Y cuando tu proyecto aumente de tamaño, separa la persistencia de la lógica y la presentación.

Cluster PHP

Continúa avanzando por PHP

Publicidad
Preguntas frecuentes

Preguntas sobre PHP con MySQL

Puedes utilizar PDO para crear una conexión entre PHP y MySQL. Después puedes preparar y ejecutar consultas SQL, enviar parámetros y recuperar resultados.

PDO es una interfaz de acceso a bases de datos disponible en PHP. Permite crear conexiones, preparar consultas, ejecutar instrucciones y recuperar resultados mediante una API consistente.

CRUD representa Create, Read, Update y Delete: las cuatro operaciones básicas para crear, consultar, modificar y eliminar información almacenada en una base de datos.

Las consultas preparadas permiten separar los datos de la estructura SQL. Son especialmente importantes cuando una consulta utiliza valores provenientes de formularios, URLs u otras fuentes externas.

Sí, es muy recomendable. PDO permite ejecutar consultas, pero necesitas comprender SQL para diseñarlas, trabajar con relaciones, utilizar JOIN, optimizar consultas y modelar correctamente la información.

Una transacción agrupa varias operaciones para que puedan confirmarse conjuntamente o revertirse si alguna falla. Resultan importantes en procesos como pedidos, pagos o movimientos de inventario.

Sí, pueden formar parte de aplicaciones grandes. La capacidad de escalar dependerá también del diseño de base de datos, arquitectura, índices, consultas, infraestructura y necesidades del proyecto.

WordPress utiliza PHP en el servidor y almacena gran parte de su información en una base de datos. Para desarrollo WordPress conviene utilizar primero las APIs de la plataforma y recurrir a consultas personalizadas cuando sea necesario.

Publicidad
Pasa de ejercicios a datos reales

Construye un CRUD completo y entenderás por qué PHP y MySQL aparecen juntos en tantas aplicaciones

Diseña una tabla, conecta PDO, utiliza consultas preparadas, crea un CRUD y después añade usuarios, relaciones, transacciones y paginación. Esa base te servirá para construir sistemas mucho mayores.

Continuar con la guía PHP →
Carrito de compra
Scroll al inicio