Laravel · Eloquent · ORM · MySQL

Eloquent en Laravel: models, relaciones, CRUD y consultas

Eloquent es el ORM de Laravel: permite representar registros de una base de datos mediante objetos PHP y expresar consultas, relaciones y operaciones CRUD a través de models. Facilita enormemente el acceso a datos, pero no elimina SQL. Para utilizar Eloquent correctamente necesitas comprender cómo están relacionadas tus tablas, qué consultas genera el ORM y cuándo una abstracción cómoda puede producir problemas de rendimiento.

Models · CRUD hasMany · belongsTo N+1 · Scopes · Pagination
Respuesta rápida

¿Qué es Eloquent en Laravel?

Eloquent es un ORM que permite trabajar con registros de una base de datos mediante clases y objetos PHP.

Normalmente una clase llamada Producto puede representar registros de una tabla de productos, mientras métodos y relaciones permiten consultar, insertar, actualizar y conectar datos.

Por ejemplo, en vez de escribir manualmente una consulta SELECT sencilla, puedes expresar:

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

Eloquent hace el código más expresivo, pero la consulta SQL continúa existiendo debajo de esa abstracción.

Publicidad
Mapa de Eloquent

Los conceptos que necesitas dominar

01

Models

Representan entidades persistidas.

02

Queries

Filtrar, ordenar y recuperar datos.

03

Relaciones

Conectan modelos entre sí.

04

Eager loading

Reduce consultas innecesarias.

05

Scopes

Reutilizan condiciones frecuentes.

06

Rendimiento

SQL, índices y consultas.

Publicidad
Antes del código

¿Qué problema intenta resolver un ORM?

Una aplicación orientada a objetos trabaja con clases, objetos, propiedades y métodos.

Una base de datos relacional trabaja con tablas, filas, columnas, claves y relaciones.

Son dos formas diferentes de representar información.

Un ORM intenta ofrecer una capa que permita trabajar con datos relacionales utilizando objetos del lenguaje.

Concepto ORM
Tabla productos
        ↓
Model Producto
        ↓
Objeto Producto
        ↓
PHP

Esto puede reducir mucho código repetitivo, pero no elimina el modelo relacional que existe debajo.

Eloquent abstrae SQL; no lo vuelve irrelevante.

Necesitas comprender tablas, claves, relaciones, índices y consultas para utilizar el ORM con criterio.

Models

Un model Eloquent representa una entidad persistida

Supongamos que tenemos una tabla llamada:

Tabla MySQL
productos

Podemos representar esos datos mediante un model:

Producto.php Laravel
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

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

A partir de ahí, la clase puede utilizarse para realizar operaciones sobre esos registros.

El model no debería entenderse simplemente como “una tabla convertida en clase”

Puede representar relaciones, reglas relacionadas con persistencia, transformaciones y comportamiento asociado a esa entidad.

Pero tampoco deberías convertir cada model en una clase gigantesca que contenga toda la lógica del sistema.

Consultas

Eloquent utiliza un query builder para construir consultas de forma expresiva

Obtener todos

SELECT Eloquent
$productos = Producto::all();

Buscar por ID

ID Eloquent
$producto = Producto::find($id);

Filtrar

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

Ordenar y limitar

Orden Eloquent
$productos = Producto::query()
    ->where('activo', true)
    ->orderByDesc('created_at')
    ->limit(10)
    ->get();

Es fácil leer este código como PHP.

Pero también necesitas imaginar qué consulta SQL puede existir debajo.

Publicidad
CRUD

Crear registros con Eloquent

Podemos insertar un producto utilizando el model.

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

El resultado es un objeto que representa el registro creado.

También puedes instanciar el model

save() Eloquent
$producto = new Producto();

$producto->nombre = 'Teclado mecánico';
$producto->precio = 69990;
$producto->activo = true;

$producto->save();

Ambos enfoques pueden ser válidos.

Lo importante es comprender qué datos estás permitiendo persistir.

Seguridad

Mass assignment merece atención cuando utilizas create() o fill()

Una práctica peligrosa sería asumir que todos los datos enviados por el usuario pueden persistirse sin control.

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

El problema es que el cliente podría enviar campos que no esperabas.

Una alternativa mucho más clara es validar primero:

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

Producto::create($datos);
$fillable no sustituye la validación ni la autorización.

Que un atributo pueda asignarse no significa que cualquier usuario tenga permiso para modificarlo.

CRUD

Actualizar y eliminar registros

Actualizar un model

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

$producto->update([
    'nombre' => 'Monitor 32"',
    'precio' => 249990
]);

Eliminar

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

$producto->delete();

Encontrar no significa autorizar

Poder recuperar un registro mediante su ID no demuestra que el usuario actual tenga permiso para modificarlo o eliminarlo.

Esa comprobación pertenece a la autorización del sistema.

Publicidad
Relaciones

Las relaciones son una de las partes más importantes de Eloquent

Las aplicaciones reales no suelen trabajar con tablas aisladas.

Un usuario puede tener pedidos.

Un pedido puede tener productos.

Un artículo puede pertenecer a una categoría.

Eloquent permite expresar estas asociaciones mediante métodos en los models.

Relación Concepto
Usuario
   │
   └── tiene muchos → Pedidos

Pedido
   │
   └── pertenece a → Usuario

Para utilizar correctamente estas relaciones, primero deberías entender primary keys, foreign keys y cardinalidad en una base de datos relacional.

hasMany

Relación uno a muchos: un usuario puede tener muchos pedidos

Dentro del model Usuario:

Usuario.php hasMany
<?php

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

Esto expresa que un usuario puede estar relacionado con múltiples pedidos.

Después puedes acceder a la relación:

Relación Eloquent
$usuario = Usuario::findOrFail($id);

$pedidos = $usuario->pedidos;

Parece simplemente acceso a una propiedad, pero puede implicar una consulta a la base de datos.

belongsTo

La relación inversa permite saber a qué usuario pertenece un pedido

Pedido.php belongsTo
<?php

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

Ahora podemos:

Acceso Eloquent
$pedido = Pedido::findOrFail($id);

$usuario = $pedido->usuario;

La base de datos normalmente mantiene la referencia mediante una foreign key.

Las relaciones Eloquent tienen mucho más sentido cuando comprendes primero las relaciones SQL.
Repasar relaciones en MySQL →
Muchos a muchos

Un pedido puede contener muchos productos y un producto aparecer en muchos pedidos

Este tipo de relación normalmente necesita una tabla intermedia.

Modelo relacional Many-to-many
pedidos
   ↓
pedido_producto
   ↑
productos

Dentro del model Pedido:

Pedido.php belongsToMany
<?php

public function productos()
{
    return $this->belongsToMany(
        Producto::class
    );
}

La tabla intermedia también puede almacenar datos propios de la relación.

Por ejemplo:

01

Cantidad.

02

Precio aplicado.

03

Descuento.

Esto demuestra que una tabla pivote no es solamente una formalidad técnica: puede representar información propia de la relación.

Publicidad
Carga de relaciones

Acceder a una relación puede ejecutar una consulta adicional

Considera:

Ejemplo Eloquent
$pedidos = Pedido::all();

foreach ($pedidos as $pedido) {

    echo $pedido->usuario->nombre;

}

Visualmente, el código parece simple.

Pero si cada acceso a:

Relación Acceso
$pedido->usuario

provoca una consulta, puedes generar muchísimas operaciones innecesarias.

Aquí aparece uno de los conceptos más importantes al trabajar con ORM.

N+1

El problema N+1 puede convertir código elegante en una aplicación lenta

Imagina que cargas 100 pedidos.

Primera consulta:

Consulta 1 Pedidos
SELECT * FROM pedidos;

Después, si cada pedido carga su usuario individualmente, podrías terminar con muchas consultas adicionales.

Problema N+1
1 consulta para pedidos
+
100 consultas para usuarios
=
101 consultas
Este problema es fácil de introducir precisamente porque Eloquent hace que acceder a relaciones resulte muy cómodo.
Eager loading

with() permite cargar relaciones que sabes que vas a necesitar

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

En lugar de esperar hasta cada acceso, indicas de antemano que necesitas la relación.

También puedes cargar varias relaciones

Relaciones with()
$pedidos = Pedido::query()
    ->with([
        'usuario',
        'productos'
    ])
    ->get();

Esto no significa que debas cargar absolutamente todas las relaciones siempre.

Cada relación incorpora datos y trabajo.

Evitar N+1 no significa cargar todo el modelo relacional en cada consulta.

Recupera lo que realmente necesita cada caso de uso.

Publicidad
Consultas eficientes

No siempre necesitas SELECT *

Si una pantalla solamente necesita:

ID, nombre y precio, puedes expresar esa necesidad.

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

Esto puede ser especialmente importante cuando las tablas contienen columnas grandes que esa operación no necesita.

La optimización empieza por entender qué necesita realmente la consulta

No por añadir técnicas complejas automáticamente.

Reutilización

Los scopes pueden expresar condiciones que repites constantemente

Supongamos que casi siempre necesitas productos activos.

Sin reutilización:

Repetición Consulta
Producto::query()
    ->where('activo', true)
    ->get();

Un scope puede encapsular esa intención.

El objetivo no es esconder todas las consultas, sino dar un nombre claro a condiciones que representan conceptos del dominio.

“Activos” comunica mejor una intención de negocio que repetir una condición técnica por toda la aplicación.
Agregados

No necesitas cargar todos los registros para contarlos

Una mala estrategia sería recuperar miles de objetos solamente para conocer cuántos existen.

Puedes preguntar directamente por el conteo.

COUNT Eloquent
$total = Producto::query()
    ->where('activo', true)
    ->count();

Lo mismo ocurre con operaciones de suma, promedio, mínimo o máximo.

Deja que la base de datos realice el trabajo que sabe hacer eficientemente.

Paginación

Una lista grande no debería cargar todos sus registros en una sola página

Si tienes 100.000 productos, esto:

Evitar Eloquent
$productos = Producto::all();

probablemente no representa lo que necesita una interfaz paginada.

Puedes solicitar una cantidad limitada por página.

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

Para conjuntos extremadamente grandes y determinados patrones de navegación, existen estrategias alternativas a offsets profundos.

Pero para empezar, lo importante es comprender que paginar también forma parte del diseño de la consulta.

Transacciones

Eloquent no elimina la necesidad de transacciones

Imagina la creación de un pedido.

Necesitas:

01

Crear pedido.

02

Crear sus líneas.

03

Actualizar inventario.

Si la operación falla a mitad, puedes terminar con datos inconsistentes.

Una transacción permite tratar varias operaciones como una unidad.

Transacción 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);

    }

});
Utilizar models no convierte automáticamente una secuencia de operaciones en atómica.

Las transacciones siguen siendo una herramienta fundamental del modelo relacional.

Publicidad
Eloquent o Query Builder

No todas las consultas necesitan convertirse en models completos

Eloquent resulta especialmente útil cuando trabajas con entidades y relaciones.

Pero existen consultas orientadas a reportes, métricas o agregaciones donde un enfoque más directo puede resultar más claro.

Laravel también proporciona Query Builder.

Query Builder Laravel
<?php

use Illuminate\Support\Facades\DB;

$ventas = DB::table('pedidos')
    ->selectRaw(
        'DATE(created_at) AS fecha, SUM(total) AS total'
    )
    ->groupByRaw(
        'DATE(created_at)'
    )
    ->get();

Elegir Eloquent no obliga a utilizarlo para absolutamente todo

Utiliza la herramienta que exprese mejor la consulta y su propósito.

SQL directo

En algunos casos una consulta SQL explícita puede ser más clara

Un ORM es una herramienta.

No una regla que prohíba escribir SQL.

Consultas particularmente complejas, reportes, agregaciones o necesidades específicas pueden justificar otras alternativas.

La decisión debería basarse en claridad y comportamiento

No en una idea de que:

“SQL es malo” o “ORM es siempre mejor”.

Base fundamental

Cuanto mejor sepas SQL, mejores decisiones podrás tomar dentro de Eloquent

JOIN, índices, transacciones, consultas y rendimiento.

PHP con MySQL →
Índices

Eloquent no puede compensar una base de datos mal indexada

Imagina una consulta que filtra constantemente millones de registros por una columna.

El problema puede estar mucho más relacionado con el diseño de índices que con Eloquent.

Un ORM puede construir la consulta, pero MySQL sigue siendo responsable de ejecutarla.

No indexes todo automáticamente

Los índices aceleran determinados patrones de lectura, pero también ocupan espacio y añaden trabajo en escrituras.

Diseña índices según las consultas reales de la aplicación.

Arquitectura

No conviertas tus models Eloquent en el lugar donde vive toda la aplicación

Un model puede representar datos, relaciones y comportamiento relacionado con esa entidad.

Pero un sistema complejo puede incluir procesos que coordinan múltiples entidades.

Por ejemplo:

01

Crear pedido.

02

Reservar stock.

03

Aplicar descuento.

04

Registrar pago.

05

Enviar notificación.

Meter todo dentro de Pedido.php puede terminar creando un model difícil de mantener.

Servicios, actions o casos de uso pueden ayudar cuando existe una responsabilidad real que separar.

Repasar POO en PHP →
Publicidad
Eliminación

No todos los registros deberían desaparecer físicamente al “eliminarlos”

En determinados sistemas necesitas conservar registros por trazabilidad, historial o recuperación.

Laravel permite trabajar con mecanismos de eliminación lógica cuando el modelo del negocio lo requiere.

Pero no conviertas soft delete en una regla universal

Existen datos que realmente deberían eliminarse y otros que deben conservarse.

Esa decisión pertenece al modelo de negocio y a los requisitos de datos, no únicamente al ORM.

APIs

Evita asumir que todo atributo del model debe exponerse en una API

Un model puede contener información que la base de datos necesita, pero que el cliente nunca debería recibir.

Por ejemplo:

01

Campos internos.

02

Información privada.

03

Metadatos administrativos.

04

Relaciones no necesarias.

La respuesta de una API debería representar el contrato que necesita el consumidor, no simplemente volcar el contenido completo del model.

REST

Eloquent resuelve persistencia; HTTP y el contrato de la API siguen siendo otra responsabilidad

JSON, recursos, status codes y seguridad.

Fundamentos de API REST →
Testing

Las consultas y relaciones importantes también deberían probarse

No basta con comprobar que una página “se ve bien”.

Puedes probar comportamientos como:

01

Crear un registro.

02

Asociar un pedido a un usuario.

03

Evitar datos inválidos.

04

Filtrar correctamente registros.

05

Mantener consistencia durante transacciones.

El objetivo no es probar que Laravel funciona.

Es comprobar que tus reglas y consultas producen el comportamiento que esperas.

Eloquent vs PDO

PDO te acerca a SQL; Eloquent te acerca al modelo de objetos

Área PDO Eloquent
SQL visible Muy directo Más abstraído
Models Debes diseñarlos Integrados
Relaciones SQL / lógica propia API expresiva
CRUD repetitivo Más manual Muy rápido
Control consulta Muy explícito Debes observar SQL generado
Laravel Posible a nivel de base PHP Integración natural

No necesitas escoger uno como si el otro estuviera prohibido.

Aprender PDO primero puede ayudarte a entender qué está abstrayendo Eloquent.

Laravel vs PHP

Eloquent es un buen ejemplo de lo que Laravel añade sobre PHP puro

Models, relaciones y consultas expresivas.

Laravel vs PHP puro →
Publicidad
Ruta de aprendizaje

En qué orden aprender Eloquent

1

SQL

SELECT, JOIN y relaciones.

2

Models

Entiende qué representa cada clase.

3

CRUD

Crear, leer, actualizar y eliminar.

4

Relaciones

belongsTo, hasMany y many-to-many.

5

Eager loading

Evita N+1.

6

Scopes

Reutiliza consultas con intención.

7

Paginación

No cargues todo de una vez.

8

Transacciones

Protege operaciones múltiples.

9

Rendimiento

SQL, índices y consultas.

10

Arquitectura

Decide cuándo no usar Eloquent.

Errores frecuentes

Los errores que más deberías evitar con Eloquent

Error No aprender SQL
Aprende SQL
Error Producto::all() para todo
Filtra
Error N+1
with()
Error Cargar todas las relaciones siempre
Selecciona
Error $request->all()
Valida
Error Ignorar índices
Analiza
Error Models gigantes
Separa
Error Usar ORM para absolutamente todo
Evalúa
Conclusión

Eloquent es potente cuando entiendes tanto los objetos PHP como la base de datos que existe debajo

Utiliza models para representar entidades persistidas.

Aprende CRUD antes de entrar a relaciones complejas.

Comprende hasMany, belongsTo y relaciones muchos a muchos.

Detecta el problema N+1 y utiliza eager loading cuando corresponda.

No recuperes columnas o registros que no necesitas.

Utiliza paginación en listados grandes.

Usa transacciones cuando varias escrituras forman una sola operación.

Aprende Query Builder y SQL para no depender de una sola abstracción.

Eloquent debería hacer tus consultas más expresivas, no impedirte comprender qué está haciendo realmente la base de datos.

Cluster Laravel

Continúa desde Eloquent hacia Laravel completo

Publicidad
Preguntas frecuentes

Preguntas sobre Eloquent en Laravel

Eloquent es el ORM de Laravel. Permite representar registros de una base de datos mediante models PHP y realizar consultas, CRUD y relaciones utilizando una API orientada a objetos.

Sí, es muy recomendable. Eloquent abstrae muchas consultas, pero SQL, relaciones, JOIN, índices y transacciones siguen siendo fundamentales para diseñar y optimizar una aplicación.

Eloquent trabaja alrededor de models y relaciones orientadas a objetos. Query Builder permite construir consultas sin necesitar representar cada resultado mediante un model Eloquent. Ambos pueden ser útiles según el tipo de consulta.

hasMany representa una relación uno a muchos. Por ejemplo, un usuario puede tener muchos pedidos. El model Usuario puede definir una relación hasMany hacia Pedido.

belongsTo expresa que un model pertenece a otro. Por ejemplo, un Pedido puede pertenecer a un Usuario. Normalmente la relación se apoya en una foreign key de la base de datos.

N+1 aparece cuando recuperas una colección y después ejecutas consultas adicionales para sus relaciones registro por registro. El eager loading permite cargar relaciones necesarias de forma más eficiente.

Eloquent ofrece una abstracción de acceso a datos mucho más orientada a models y relaciones. PDO es una interfaz de PHP de menor nivel para trabajar con bases de datos. Aprender PDO y SQL puede ayudarte a comprender mejor lo que el ORM abstrae.

No necesariamente. Eloquent resulta muy cómodo para trabajar con models y relaciones, pero determinadas consultas, reportes, agregaciones o necesidades específicas pueden expresarse mejor mediante Query Builder o SQL más directo.

Publicidad
Eloquent sin magia

Aprende a leer Eloquent como PHP y, al mismo tiempo, como una consulta a una base de datos

Empieza por models y CRUD, añade relaciones, aprende a detectar N+1, utiliza eager loading y después profundiza en scopes, paginación, transacciones y rendimiento. Cuanto mejor entiendas SQL, más potente será Eloquent en tus manos.

Continuar aprendiendo Laravel →
Carrito de compra
Scroll al inicio