Laravel · MySQL · Eloquent · Migraciones

Laravel con MySQL: conexión, migraciones, Eloquent y consultas

Laravel puede conectarse a MySQL, crear y modificar tablas mediante migraciones, consultar datos con Query Builder o Eloquent y administrar relaciones, índices, transacciones y paginación dentro de una misma aplicación. Pero trabajar bien con Laravel y MySQL requiere algo más que configurar cinco variables en el archivo .env: debes comprender cómo está diseñada la base de datos y qué consultas termina ejecutando tu aplicación.

.env · Migrations Eloquent · Query Builder Índices · Transacciones · N+1
Respuesta rápida

¿Cómo conectar Laravel con MySQL?

Laravel puede conectarse a MySQL configurando la conexión de base de datos de la aplicación, normalmente mediante variables de entorno.

Una configuración habitual utiliza valores como:

.env MySQL
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mi_aplicacion
DB_USERNAME=usuario
DB_PASSWORD=clave_segura

Después puedes utilizar migraciones para crear tablas, Eloquent para trabajar con models y relaciones, Query Builder para consultas más directas y transacciones para proteger operaciones que deben completarse como una unidad.

Laravel facilita la interacción con MySQL, pero conocer SQL sigue siendo esencial para diseñar relaciones, índices y consultas eficientes.

Publicidad
Capa de datos

Laravel ofrece varias formas de trabajar con MySQL

01

Migraciones

Definen y versionan la estructura de la base de datos.

02

Query Builder

Construye consultas mediante una API de Laravel.

03

Eloquent

Representa registros mediante models.

04

Relaciones

Conecta usuarios, pedidos, productos y otras entidades.

05

Transacciones

Protegen operaciones de múltiples pasos.

06

Índices

Mejoran determinados patrones de consulta.

Publicidad
Antes de conectar

Laravel no crea automáticamente una buena base de datos

El framework facilita muchísimo la persistencia, pero las decisiones importantes siguen siendo tuyas.

Debes definir correctamente:

01

Qué entidades existen.

02

Qué datos necesita cada una.

03

Cómo se relacionan.

04

Qué campos son únicos.

05

Qué columnas necesitan índices.

06

Qué operaciones necesitan transacciones.

Una mala estructura continuará siendo una mala estructura aunque utilices Eloquent.

Laravel administra la interacción; MySQL sigue siendo una base de datos relacional.

Aprende modelado, SQL y relaciones además del framework.

Aprender PHP con MySQL →
Configuración

Configura MySQL mediante las variables de entorno de la aplicación

Una conexión típica puede utilizar:

.env Laravel + MySQL
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tienda
DB_USERNAME=tienda_user
DB_PASSWORD=una_clave_segura

DB_CONNECTION

Indica qué conexión utilizará la aplicación.

DB_HOST

Define dónde está el servidor MySQL.

DB_PORT

Corresponde al puerto utilizado por el servicio.

DB_DATABASE

Es la base que utilizará la aplicación.

DB_USERNAME y DB_PASSWORD

Son las credenciales utilizadas para autenticarse contra MySQL.

No publiques credenciales reales dentro del repositorio.

La configuración sensible debe permanecer fuera del código que compartes públicamente.

Debugging inicial

Si cambias la configuración y Laravel sigue usando valores anteriores, revisa la caché de configuración

En determinados entornos, la configuración puede haber sido almacenada para mejorar el arranque de la aplicación.

Durante desarrollo puede ser útil limpiar esa configuración cuando cambias variables relacionadas con la conexión.

Artisan Configuración
php artisan config:clear

Si la aplicación continúa sin conectarse, revisa también:

01

Nombre de la base.

02

Usuario MySQL.

03

Contraseña.

04

Host.

05

Puerto.

06

Permisos del usuario.

Publicidad
Migraciones

Las migraciones permiten que la estructura de MySQL forme parte del código del proyecto

Supongamos que necesitamos una tabla de productos.

Una migración puede describirla:

create_products_table Laravel
<?php

Schema::create('productos', function (Blueprint $table) {

    $table->id();

    $table->string(
        'nombre',
        150
    );

    $table->decimal(
        'precio',
        12,
        2
    );

    $table->boolean('activo')
        ->default(true);

    $table->timestamps();
});

Después puedes aplicar las migraciones.

Terminal Artisan
php artisan migrate

¿Por qué es mejor que modificar tablas manualmente?

Porque el cambio puede quedar documentado, versionado y reproducible entre:

desarrollo, pruebas, staging y producción.

Diseño de columnas

Elige tipos de datos según lo que representa cada valor

No todas las columnas deberían ser strings simplemente porque resulta cómodo.

Laravel permite expresar distintos tipos dentro de las migraciones.

Texto

String Migration
$table->string('nombre', 150);

Booleano

Boolean Migration
$table->boolean('activo')
    ->default(true);

Decimal

Decimal Migration
$table->decimal(
    'precio',
    12,
    2
);

El diseño debería reflejar la semántica del dato y las operaciones que necesitarás realizar con él.

Claves foráneas

Las relaciones deberían existir también en la base de datos, no solamente en Eloquent

Supongamos que un pedido pertenece a un usuario.

La tabla pedidos puede almacenar una referencia al usuario.

Migration Foreign key
<?php

$table->foreignId('usuario_id')
    ->constrained('usuarios');

Conceptualmente:

Relación MySQL
usuarios
   │
   │ id
   ↓
pedidos.usuario_id

Esto ayuda a preservar integridad entre registros.

Piensa también qué debería ocurrir al eliminar el registro padre

Según el dominio, podrías necesitar:

restringir, mantener, establecer null o eliminar registros relacionados.

No agregues cascade delete automáticamente a todas las relaciones.

Eliminar un usuario y borrar automáticamente toda su información puede ser correcto en un sistema e incorrecto en otro.

Publicidad
Índices

Los índices deben diseñarse según las consultas reales de tu aplicación

Supongamos que buscas constantemente productos por SKU.

Si además el SKU debe ser único, la base puede representar esa regla.

Índice único Migration
$table->string('sku', 100)
    ->unique();

Para otras columnas puedes definir índices sin necesidad de imponer unicidad.

Index Migration
$table->index('estado');

No indexes todas las columnas “por si acaso”

Los índices pueden acelerar búsquedas, filtros y joins, pero también:

ocupan espacio y añaden trabajo durante INSERT, UPDATE y DELETE.

Los índices son una decisión de diseño basada en patrones de consulta, no una decoración de la migración.
Índices compuestos

Varias columnas pueden formar parte del mismo patrón de búsqueda

Imagina que una aplicación consulta repetidamente pedidos por:

usuario y estado.

Podría existir un caso para evaluar un índice compuesto.

Composite index Migration
$table->index([
    'usuario_id',
    'estado'
]);

Pero para diseñarlo correctamente necesitas observar cómo consultas realmente los datos.

El orden y composición de un índice importan.

Por eso, cuando la optimización empieza a ser relevante, conviene analizar la consulta y el plan que utiliza MySQL.

Eloquent

Crea un model para trabajar con los registros desde PHP

Para la tabla productos podemos utilizar:

Producto.php Eloquent
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

final class Producto extends Model
{
    protected $fillable = [
        'nombre',
        'sku',
        'precio',
        'activo'
    ];

    protected function casts(): array
    {
        return [
            'activo' => 'boolean',
            'precio' => 'decimal:2'
        ];
    }
}

Ahora puedes consultar los registros mediante el model.

Consulta Eloquent
$productos = Producto::query()
    ->where('activo', true)
    ->orderBy('nombre')
    ->get();

Los casts ayudan a representar determinados valores con tipos adecuados dentro del model.

CRUD

Laravel puede realizar las cuatro operaciones básicas sobre MySQL mediante Eloquent

Crear

CREATE Eloquent
$producto = Producto::create([
    'nombre' => 'Monitor 27"',
    'sku' => 'MON-27-001',
    'precio' => 199990,
    'activo' => true
]);

Leer

READ Eloquent
$producto = Producto::findOrFail($id);

Actualizar

UPDATE Eloquent
$producto->update([
    'precio' => 189990
]);

Eliminar

DELETE Eloquent
$producto->delete();
CRUD no significa que cualquiera pueda ejecutar esas operaciones.

Validación y autorización siguen siendo responsabilidades diferentes.

Entrada de datos

Valida antes de enviar información a MySQL

Una creación segura no debería comenzar con:

Evitar Entrada completa
Producto::create(
    $request->all()
);

Es preferible definir qué campos espera la operación.

Validación Laravel
$datos = $request->validate([
    'nombre' => [
        'required',
        'string',
        'max:150'
    ],
    'sku' => [
        'required',
        'string',
        'max:100'
    ],
    'precio' => [
        'required',
        'numeric',
        'min:0'
    ]
]);

$producto = Producto::create($datos);

La validación comprueba la forma del dato.

Las reglas de negocio pueden necesitar comprobaciones adicionales.

Publicidad
Relaciones

MySQL define la relación y Eloquent la expresa desde PHP

Imagina esta estructura:

Datos Relación
usuarios
   │
   │ 1
   ↓
pedidos
   │
   │ N
   ↓
items_pedido

Dentro del model Usuario:

Usuario.php hasMany
<?php

public function pedidos()
{
    return $this->hasMany(
        Pedido::class
    );
}

Y dentro de Pedido:

Pedido.php belongsTo
<?php

public function usuario()
{
    return $this->belongsTo(
        Usuario::class
    );
}

Eloquent hace cómoda la navegación entre objetos, pero la integridad y estructura de esos datos pertenecen al modelo relacional.

Eloquent

Profundiza en models, relaciones, eager loading y N+1

El ORM es una capa sobre MySQL, no su sustituto.

Aprender Eloquent →
Rendimiento

Una relación cómoda puede provocar decenas o cientos de consultas

Este código parece sencillo:

Posible N+1 Eloquent
$pedidos = Pedido::all();

foreach ($pedidos as $pedido) {

    echo $pedido->usuario->nombre;

}

Si cada acceso al usuario dispara una consulta adicional, el número de operaciones puede crecer rápidamente.

Eager loading

with() Eloquent
$pedidos = Pedido::query()
    ->with('usuario')
    ->get();

Ahora indicas que la relación será necesaria durante esa consulta.

Eloquent puede ocultar la cantidad de SQL que ejecutas. Aprende a pensar en objetos y consultas al mismo tiempo.
Query Builder

No todas las consultas necesitan pasar por un model Eloquent

Para determinadas operaciones puedes utilizar Query Builder.

Query Builder Laravel
<?php

use Illuminate\Support\Facades\DB;

$productos = DB::table('productos')
    ->select([
        'id',
        'nombre',
        'precio'
    ])
    ->where('activo', true)
    ->orderBy('nombre')
    ->get();

Esto puede resultar apropiado para:

01

Reportes.

02

Consultas agregadas.

03

Operaciones sin model.

04

Consultas más cercanas al esquema.

La pregunta no es: “¿qué herramienta es mejor?”.

Es: “¿qué herramienta expresa mejor esta operación?”.

Publicidad
Agregaciones

Deja que MySQL haga el trabajo que corresponde a la base de datos

Si quieres saber cuántos pedidos están pagados, no necesitas recuperar todos los pedidos para contarlos en PHP.

COUNT Eloquent
$total = Pedido::query()
    ->where('estado', 'pagado')
    ->count();

Lo mismo ocurre con sumas.

SUM Eloquent
$ventas = Pedido::query()
    ->where('estado', 'pagado')
    ->sum('total');

La base de datos está diseñada para realizar este tipo de operaciones eficientemente.

Paginación

No recuperes toda una tabla para mostrar veinte registros

Una tienda podría tener decenas o cientos de miles de productos.

Esto:

Evitar Listado completo
$productos = Producto::all();

no debería ser la estrategia por defecto para una interfaz paginada.

Puedes recuperar un conjunto limitado.

Pagination Laravel
$productos = Producto::query()
    ->where('activo', true)
    ->orderBy('id')
    ->paginate(20);

La paginación reduce datos transferidos y memoria utilizada por la aplicación.

Transacciones

Usa transacciones cuando varias operaciones deben completarse juntas

Imagina que crear un pedido requiere:

01

Crear pedido.

02

Insertar sus items.

03

Actualizar stock.

Si la tercera operación falla, quizá no quieras conservar las dos primeras.

Transaction Laravel
<?php

use Illuminate\Support\Facades\DB;

DB::transaction(function () use ($datos) {

    $pedido = Pedido::create([
        'usuario_id' => $datos['usuario_id'],
        'total' => $datos['total']
    ]);

    foreach ($datos['items'] as $item) {

        $pedido->items()->create($item);

    }

});

Si se produce una excepción durante la operación, la transacción permite revertir los cambios correspondientes.

Eloquent no convierte automáticamente una secuencia de escrituras en una operación atómica.
Concurrencia

Dos usuarios pueden intentar modificar los mismos datos al mismo tiempo

Esto aparece en situaciones como:

01

Stock limitado.

02

Reservas.

03

Saldos.

04

Cupos.

Una aplicación que primero consulta stock y después lo descuenta sin considerar concurrencia puede producir resultados inconsistentes.

Las transacciones pueden formar parte de la solución

Y determinadas operaciones pueden necesitar bloqueos o estrategias específicas de concurrencia.

Los problemas de concurrencia no se solucionan solamente porque utilices Eloquent.

Siguen siendo problemas de consistencia de datos.

Publicidad
Datos iniciales

Seeders permiten insertar datos necesarios para desarrollar o inicializar determinados entornos

Durante el desarrollo puedes necesitar:

01

Roles iniciales.

02

Categorías.

03

Configuraciones.

04

Datos de prueba.

Un seeder permite representar ese proceso mediante código.

Seeder Eloquent
<?php

Producto::create([
    'nombre' => 'Producto de prueba',
    'sku' => 'TEST-001',
    'precio' => 9990,
    'activo' => true
]);

No confundas datos de desarrollo con datos de producción

La estrategia de seed debería distinguir claramente información necesaria de datos meramente ficticios.

Datos de prueba

Factories pueden generar registros útiles para testing y desarrollo

Probar una aplicación con solamente dos registros puede esconder problemas que aparecen con volúmenes mayores.

Los datos generados pueden ayudarte a probar:

01

Paginación.

02

Filtros.

03

Relaciones.

04

Consultas grandes.

05

Interfaces con muchos resultados.

Esto resulta mucho más útil que crear manualmente cientos de filas.

Desarrollo

Poder reconstruir una base de desarrollo reduce configuraciones manuales difíciles de repetir

Una de las ventajas de migraciones y seeders es que puedes describir gran parte del estado inicial necesario por la aplicación.

Esto ayuda cuando:

01

Entra un nuevo desarrollador.

02

Creas un entorno de pruebas.

03

Necesitas reconstruir datos locales.

Operaciones destructivas de base de datos deben utilizarse con extremo cuidado y nunca asumirse seguras en producción.
Publicidad
Debugging SQL

Aprende a inspeccionar qué consulta estás construyendo

Una consulta Eloquent puede resultar muy legible:

Eloquent Builder
$query = Producto::query()
    ->where('activo', true)
    ->where('precio', '>', 50000);

Durante debugging puede resultar útil inspeccionar el SQL que el builder representa.

SQL Debug
$sql = $query->toSql();

Recuerda que una representación de este tipo puede contener placeholders en lugar de los valores finales.

La pregunta importante es qué está haciendo MySQL

Si una consulta es lenta, analiza:

01

Filtros.

02

JOIN.

03

Índices.

04

Ordenamientos.

05

Cantidad de filas examinadas.

Selección de datos

Recupera solamente las columnas que necesita el caso de uso cuando eso aporte valor

Un listado quizá solo necesita:

ID, nombre, precio y estado.

SELECT Eloquent
$productos = Producto::query()
    ->select([
        'id',
        'nombre',
        'precio',
        'activo'
    ])
    ->where('activo', true)
    ->paginate(20);

Esto puede reducir datos innecesarios cuando una tabla contiene columnas grandes.

Tampoco optimices cada consulta prematuramente

La optimización debería responder a necesidades reales y mediciones, no solamente a reglas aplicadas mecánicamente.

SQL avanzado

Usar Laravel no significa que SQL directo esté prohibido

Determinados:

01

Reportes.

02

Agregaciones.

03

Consultas especializadas.

04

Procesos de análisis.

pueden resultar más claros usando Query Builder o expresiones SQL controladas.

El objetivo no es forzar toda consulta a parecer un model.

El objetivo es mantener código legible, seguro y eficiente.

Laravel + MySQL + API

La base de datos no debería definir automáticamente la respuesta de tu API

Si tienes un model Usuario con veinte atributos, eso no significa que debas devolverlos todos al cliente.

Una API debería exponer únicamente la información necesaria para ese contrato.

Response Concepto
{
    "id": 45,
    "nombre": "Daniel",
    "estado": "activo"
}

La estructura interna de MySQL y la estructura pública de una API son decisiones relacionadas, pero no necesariamente idénticas.

Fundamentos REST

Comprende primero HTTP, JSON, autenticación y contratos de API

Después Laravel puede ayudarte a construir esa capa con mucha rapidez.

Aprender API REST con PHP →
Arquitectura

No mezcles queries, HTML y reglas de negocio dentro del mismo controller

Laravel permite realizar una consulta desde prácticamente cualquier lugar de la aplicación.

Eso no significa que sea una buena idea hacerlo sin una estructura.

Un controller debería evitar convertirse en algo como:

Evitar Controller gigante
Request
↓
Validación
↓
20 consultas
↓
Reglas de negocio
↓
Pago
↓
Email
↓
HTML
↓
Response

Cuando el proceso crece, separa responsabilidades con criterio.

Laravel organiza la infraestructura, pero la arquitectura del negocio sigue siendo responsabilidad del desarrollador.
POO y arquitectura en PHP →
Publicidad
Seguridad

Eloquent reduce algunos riesgos de consultas, pero la seguridad de los datos va mucho más allá

Debes seguir pensando en:

01

Validación.

02

Autorización.

03

Mass assignment.

04

Exposición de información.

05

Credenciales MySQL.

06

Backups.

Utiliza un usuario MySQL adecuado para la aplicación

No necesitas entregar privilegios ilimitados simplemente para ejecutar consultas del sistema.

No muestres errores SQL internos al usuario final

Los detalles técnicos pueden registrarse de manera apropiada, mientras el usuario recibe una respuesta controlada.

Producción

Las migraciones forman parte del despliegue, pero deben ejecutarse con criterio

Un cambio sencillo en desarrollo puede ser mucho más delicado sobre una tabla con millones de filas.

Antes de modificar la base de producción, considera:

01

Backups.

02

Impacto de locks.

03

Compatibilidad del código.

04

Duración de la operación.

05

Plan de recuperación.

“Funciona en mi base local” no demuestra que una migración sea inocua sobre una base grande de producción.
Proyecto práctico

Construye una tienda mínima para practicar Laravel con MySQL

Puedes modelar:

Modelo de datos Proyecto
usuarios
   ↓
pedidos
   ↓
items_pedido
   ↑
productos
   ↑
categorias

Este proyecto permite practicar:

01

Migraciones.

02

Foreign keys.

03

Índices.

04

Eloquent.

05

Relaciones.

06

N+1.

07

Transacciones.

08

Paginación.

Añade reglas reales

Por ejemplo:

un SKU no puede repetirse, un pedido debe pertenecer a un usuario y una compra no debería dejar stock negativo.

Ahí empiezas a aprender bases de datos de verdad y no solamente sintaxis del framework.

Ruta recomendada

En qué orden aprender Laravel con MySQL

1

SQL básico

SELECT, INSERT, UPDATE y DELETE.

2

Conexión

Configura Laravel con MySQL.

3

Migraciones

Define tablas mediante código.

4

Foreign keys

Modela relaciones reales.

5

Eloquent

Models y CRUD.

6

Relaciones

hasMany, belongsTo y pivots.

7

Índices

Optimiza patrones reales.

8

Transacciones

Protege operaciones múltiples.

9

Rendimiento

Detecta N+1 y queries lentas.

10

Producción

Backups, migraciones y monitoreo.

Errores frecuentes

Qué evitar al trabajar con Laravel y MySQL

Error Aprender Eloquent sin SQL
Aprende SQL
Error No usar foreign keys
Integridad
Error Indexar todo
Analiza
Error Ignorar N+1
with()
Error Producto::all() en listados enormes
Pagina
Error Varias escrituras sin transacción
Atomicidad
Error Credenciales en Git
Protege
Error Migrar producción sin evaluar impacto
Planifica
Conclusión

Laravel facilita MySQL cuando entiendes lo que ocurre debajo del framework

Configura correctamente la conexión de la aplicación.

Utiliza migraciones para versionar el esquema.

Modela relaciones con foreign keys reales.

Añade índices según patrones de consulta.

Utiliza Eloquent cuando trabajar con models aporte claridad.

Usa Query Builder o SQL cuando expresen mejor determinadas consultas.

Detecta N+1, pagina listados grandes y evita recuperar información innecesaria.

Protege operaciones de múltiples escrituras mediante transacciones cuando corresponda.

Laravel puede hacer que trabajar con MySQL sea mucho más cómodo, pero la calidad de tu aplicación seguirá dependiendo de cuánto entiendas modelado relacional, SQL, índices, consistencia y rendimiento.

Cluster Laravel

Continúa profundizando en Laravel y bases de datos

Publicidad
Preguntas frecuentes

Preguntas sobre Laravel con MySQL

Configura la conexión MySQL de la aplicación con el host, puerto, nombre de base, usuario y contraseña correspondientes. Laravel utiliza esa configuración para ejecutar migraciones, Query Builder y Eloquent.

No necesariamente. Laravel puede trabajar con distintas soluciones de persistencia y bases de datos. MySQL es una opción muy habitual para aplicaciones web, pero no es la única.

Son archivos que describen cambios en la estructura de la base de datos. Permiten crear, modificar y versionar tablas, columnas, índices y relaciones como parte del proyecto.

MySQL es el sistema de base de datos. Eloquent es una capa de Laravel para consultar y manipular esos datos mediante models y objetos PHP. Eloquent termina generando operaciones que la base de datos ejecuta.

Sí, es muy recomendable. SQL te permite comprender consultas, relaciones, JOIN, índices, agregaciones y transacciones. Esa base resulta clave para utilizar Eloquent y Query Builder correctamente.

Una foreign key representa una relación entre registros de tablas distintas. Por ejemplo, pedidos.usuario_id puede referenciar usuarios.id. Las migraciones permiten definir estas relaciones desde Laravel.

Cuando varias operaciones de base de datos forman una sola operación lógica y no quieres que únicamente una parte quede aplicada si ocurre un error. Crear un pedido y sus líneas es un ejemplo habitual.

No. Eloquent facilita escribir consultas, pero el rendimiento también depende del diseño de tablas, índices, relaciones, volumen, paginación y SQL generado. Necesitas observar el comportamiento real de MySQL.

Publicidad
Laravel + datos reales

No aprendas Laravel con MySQL como una colección de comandos de Eloquent

Diseña primero los datos, crea migraciones, define relaciones, entiende SQL, construye consultas y observa cómo responde MySQL. Después Eloquent y Query Builder se convierten en herramientas mucho más poderosas, porque sabes qué están abstrayendo.

Continuar con Eloquent →
Carrito de compra
Scroll al inicio