Saltar al contenido principal

¿Qué es Eloquent ORM?

Laravel incluye un mapeador objeto-relacional (ORM) llamado Eloquent. Eloquent simplifica la interacción con la base de datos e implementa el patrón ActiveRecord. Con Eloquent, defines una clase “modelo” por cada tabla de la base de datos. A través del modelo puedes obtener, insertar, actualizar y eliminar registros.
Antes de usar Eloquent, configura la conexión a la base de datos en config/database.php. Por defecto se usan las variables DB_* del archivo .env.

Crear un modelo

Genera un modelo con el comando Artisan make:model.
php artisan make:model Post
Para crear también la migración, usa la opción -m.
php artisan make:model Post -m
Los modelos se crean en el directorio app/Models.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    // ...
}

Correspondencia entre modelo y tabla

Eloquent deduce el nombre de la tabla a partir del nombre de la clase. El nombre en snake_case y en plural se convierte en el nombre de la tabla.
ModeloTabla
Postposts
Userusers
AirTrafficControllerair_traffic_controllers
Si la tabla no sigue la convención, indícalo con la propiedad $table.
class Post extends Model
{
    protected $table = 'blog_posts';
}

Timestamps

Por defecto Eloquent gestiona automáticamente las columnas created_at y updated_at. Si añades $table->timestamps() en la migración, se rellenan solas al guardar o actualizar. Para desactivarlo, pon $timestamps a false.
class Post extends Model
{
    public $timestamps = false;
}

Protección de mass assignment

Al guardar datos en bloque con Eloquent hay que configurar la protección de mass assignment.

fillable

Indica las columnas asignables con la propiedad $fillable.
class Post extends Model
{
    protected $fillable = [
        'user_id',
        'title',
        'body',
        'published',
    ];
}

guarded

Al contrario, $guarded indica columnas no asignables.
class Post extends Model
{
    // Protege solo la clave primaria y permite el resto
    protected $guarded = ['id'];
}
Si $guarded es un array vacío se permite la asignación a todas las columnas. Al pasar directamente entrada del usuario hay riesgo de sobrescribir columnas no previstas, así que se recomienda usar $fillable con las columnas permitidas explícitas.

Flujo de ejecución de una consulta Eloquent

Cómo se ejecuta internamente una consulta como User::where()->get():

Operaciones CRUD básicas

Obtener registros (Read)

Todos los registros:
use App\Models\Post;

$posts = Post::all();
Con condiciones:
// Posts publicados
$publishedPosts = Post::where('published', true)->get();

// El primero
$post = Post::where('published', true)->first();

// Por ID
$post = Post::find(1);

// Devuelve 404 si no existe
$post = Post::findOrFail(1);

Crear registros (Create)

Inserta un registro con create (necesita $fillable).
$post = Post::create([
    'title' => 'Mi primer post',
    'body' => 'Laravel es un framework increíble.',
    'published' => true,
]);
También creando una instancia y asignando propiedades.
$post = new Post;
$post->title = 'Mi primer post';
$post->body = 'Laravel es un framework increíble.';
$post->save();

Actualizar registros (Update)

Recupera el modelo, cambia valores y llama a save.
$post = Post::find(1);
$post->title = 'Título actualizado';
$post->save();
update permite actualizar varias columnas de una vez.
Post::find(1)->update([
    'title' => 'Título actualizado',
    'published' => true,
]);
También actualizar varios registros que cumplan una condición.
Post::where('published', false)->update(['published' => true]);

Eliminar registros (Delete)

Elimina con delete.
$post = Post::find(1);
$post->delete();
También puedes eliminar por ID directamente.
Post::destroy(1);

// Varios IDs a la vez
Post::destroy([1, 2, 3]);

Métodos de consulta básicos

MétodoDescripción
Post::all()Obtiene todos los registros
Post::find($id)Obtiene por ID (null si no existe)
Post::findOrFail($id)Obtiene por ID (404 si no existe)
Post::where('column', 'value')->get()Registros que cumplen la condición
Post::where('column', 'value')->first()Primer registro que cumple la condición
Post::where('column', 'value')->count()Cantidad que cumple la condición
Post::orderBy('created_at', 'desc')->get()Orden concreto
Post::latest()->get()Descendente por created_at
Post::limit(10)->get()Limita el número

Ejemplo práctico: operaciones con el modelo Post

Controlador que opera sobre la tabla posts creada mediante migración.
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    // Muestra la lista de posts
    public function index(): View
    {
        $posts = Post::where('published', true)
            ->latest()
            ->get();

        return view('posts.index', ['posts' => $posts]);
    }

    // Crea un post
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
            'published' => ['boolean'],
        ]);

        Post::create([
            ...$validated,
            'user_id' => $request->user()->id,
        ]);

        return redirect('/posts');
    }

    // Actualiza un post
    public function update(Request $request, Post $post): RedirectResponse
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
        ]);

        $post->update($validated);

        return redirect('/posts');
    }

    // Elimina un post
    public function destroy(Post $post): RedirectResponse
    {
        $post->delete();

        return redirect('/posts');
    }
}
Al escribir Post $post como argumento del método, Laravel resuelve automáticamente el modelo desde el parámetro de la ruta (route model binding). Ya no necesitas escribir Post::findOrFail($id) a mano.

Ciclo de vida de los eventos del modelo

Flujo de eventos al invocar save(). Los eventos difieren entre creación y actualización, pero saving y saved se disparan en ambos casos.

Próximos pasos

Migraciones

Repasa cómo crear con migraciones las tablas que usa Eloquent.
Última modificación el 13 de julio de 2026