> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Introducción a Eloquent

> Explicamos cómo manipular datos de la base de datos con Eloquent, el ORM de Laravel.

## ¿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.

<Info>
  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`.
</Info>

## Crear un modelo

Genera un modelo con el comando Artisan `make:model`.

```shell theme={null}
php artisan make:model Post
```

Para crear también la migración, usa la opción `-m`.

```shell theme={null}
php artisan make:model Post -m
```

Los modelos se crean en el directorio `app/Models`.

```php theme={null}
<?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.

| Modelo                 | Tabla                     |
| ---------------------- | ------------------------- |
| `Post`                 | `posts`                   |
| `User`                 | `users`                   |
| `AirTrafficController` | `air_traffic_controllers` |

Si la tabla no sigue la convención, indícalo con la propiedad `$table`.

```php theme={null}
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`.

```php theme={null}
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`.

```php theme={null}
class Post extends Model
{
    protected $fillable = [
        'user_id',
        'title',
        'body',
        'published',
    ];
}
```

### guarded

Al contrario, `$guarded` indica columnas no asignables.

```php theme={null}
class Post extends Model
{
    // Protege solo la clave primaria y permite el resto
    protected $guarded = ['id'];
}
```

<Warning>
  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.
</Warning>

## Flujo de ejecución de una consulta Eloquent

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

```mermaid theme={null}
flowchart LR
    A["User::where('active', true)"] --> B["Construcción del query builder"]
    B --> C["Llamada a ->get()"]
    C --> D["Generación del SQL"]
    D --> E["Ejecución en la base de datos"]
    E --> F["Se convierte a modelos Eloquent"]
    F --> G["Se devuelve como Collection"]
```

## Operaciones CRUD básicas

### Obtener registros (Read)

Todos los registros:

```php theme={null}
use App\Models\Post;

$posts = Post::all();
```

Con condiciones:

```php theme={null}
// 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`).

```php theme={null}
$post = Post::create([
    'title' => 'Mi primer post',
    'body' => 'Laravel es un framework increíble.',
    'published' => true,
]);
```

También creando una instancia y asignando propiedades.

```php theme={null}
$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`.

```php theme={null}
$post = Post::find(1);
$post->title = 'Título actualizado';
$post->save();
```

`update` permite actualizar varias columnas de una vez.

```php theme={null}
Post::find(1)->update([
    'title' => 'Título actualizado',
    'published' => true,
]);
```

También actualizar varios registros que cumplan una condición.

```php theme={null}
Post::where('published', false)->update(['published' => true]);
```

### Eliminar registros (Delete)

Elimina con `delete`.

```php theme={null}
$post = Post::find(1);
$post->delete();
```

También puedes eliminar por ID directamente.

```php theme={null}
Post::destroy(1);

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

## Métodos de consulta básicos

| Método                                       | Descripció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 theme={null}
<?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');
    }
}
```

<Tip>
  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.
</Tip>

## 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.

```mermaid theme={null}
flowchart TD
    A["Crear nueva instancia"] --> B{"save()"}
    B --> I["Evento saving"]
    I -->|"Nuevo"| C["Evento creating"]
    C --> D["INSERT"]
    D --> E["Evento created"]
    I -->|"Actualización"| F["Evento updating"]
    F --> G["UPDATE"]
    G --> H["Evento updated"]
    E --> J["Evento saved"]
    H --> J
```

## Próximos pasos

<Card title="Migraciones" icon="table" href="/es/migrations">
  Repasa cómo crear con migraciones las tablas que usa Eloquent.
</Card>


## Related topics

- [Introducción a las relaciones de Eloquent](/es/eloquent-relationships.md)
- [Colecciones Eloquent](/es/eloquent-collections.md)
- [Introducción a la autenticación](/es/authentication.md)
- [Serialización en Eloquent](/es/eloquent-serialization.md)
- [⚡Introducción a Livewire 4 — Crear UIs reactivas sin JavaScript](/es/blog/livewire-introduction.md)
