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

# Sesión

> Cómo mantener datos entre solicitudes usando la sesión HTTP de Laravel

## ¿Qué es la sesión?

HTTP es un protocolo sin estado. Es decir, HTTP en sí mismo no tiene un mecanismo para mantener información de un usuario entre solicitudes.
La funcionalidad de sesión de Laravel ofrece un modo de conservar datos del usuario a lo largo de varias solicitudes.

Guarda en la sesión información que quieras mantener entre solicitudes: estado de inicio de sesión, productos del carrito, datos de un formulario en curso, etc.

## Configuración del driver de sesión

La configuración se encuentra en `config/session.php`.
Puedes cambiar el driver con la variable de entorno `SESSION_DRIVER` (en `.env`).

```ini theme={null}
SESSION_DRIVER=database
```

Los drivers que Laravel soporta de serie son:

| Driver     | Resumen                                                                 |
| ---------- | ----------------------------------------------------------------------- |
| `file`     | Guarda como archivos en `storage/framework/sessions` (por defecto)      |
| `cookie`   | Guarda en el navegador como cookies cifradas                            |
| `database` | Guarda en una tabla de la base de datos                                 |
| `redis`    | Guarda en Redis (rápido)                                                |
| `array`    | Guarda en un array de PHP (para pruebas; no persiste entre solicitudes) |

<Info>
  En un proyecto por defecto de Laravel, el driver configurado es `database`. Para usar este driver hace falta la tabla `sessions`, pero ya está incluida en la migración por defecto, así que funciona sin ajustes.
</Info>

## Formas de acceder a la sesión

Hay dos formas de acceder: usando métodos de la instancia `Request` o usando el helper global `session()`.

### Usando la instancia Request

Recibe `Request` como type-hint en el método del controlador y accede con `$request->session()`.

```php theme={null}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\View\View;

class DashboardController extends Controller
{
    public function index(Request $request): View
    {
        $username = $request->session()->get('username');

        return view('dashboard', ['username' => $username]);
    }
}
```

### Usando el helper global `session()`

El helper `session()` puede invocarse desde cualquier sitio: controladores, vistas, etc.

```php theme={null}
// Obtener un valor
$value = session('key');

// Obtener con valor por defecto
$value = session('key', 'Valor por defecto');

// Guardar un valor
session(['key' => 'value']);
```

<Tip>
  En pruebas puedes verificar con `assertSessionHas` en ambos casos. Dentro de un controlador, usar `$request->session()` deja explícita la dependencia y resulta más claro.
</Tip>

## Operaciones sobre la sesión

### Obtener datos

```php theme={null}
// Obtener por clave
$value = $request->session()->get('key');

// Con valor por defecto
$value = $request->session()->get('key', 'default');

// Valor por defecto mediante un closure
$value = $request->session()->get('key', function () {
    return 'default';
});

// Obtener todos los datos de la sesión
$data = $request->session()->all();
```

### Comprobar la existencia

```php theme={null}
// true si existe y no es null
if ($request->session()->has('user_id')) {
    // ...
}

// true si existe aunque sea null
if ($request->session()->exists('user_id')) {
    // ...
}

// true si no existe
if ($request->session()->missing('user_id')) {
    // ...
}
```

Presta atención a la diferencia entre `has` y `exists`:

| Método   | Con valor `null` |
| -------- | ---------------- |
| `has`    | Devuelve `false` |
| `exists` | Devuelve `true`  |

### Guardar datos

```php theme={null}
// A través de la instancia Request
$request->session()->put('user_name', 'Tanaka');

// A través del helper global
session(['user_name' => 'Tanaka']);

// Añadir a un array
$request->session()->push('cart.items', ['id' => 1, 'name' => 'Producto A']);
```

### Eliminar datos

```php theme={null}
// Elimina una clave
$request->session()->forget('user_name');

// Elimina varias claves de una vez
$request->session()->forget(['user_name', 'cart']);

// Elimina todos los datos de la sesión
$request->session()->flush();
```

## Datos flash

Los datos flash son datos de sesión válidos **solo en la siguiente solicitud**.
Se usan para información que solo hay que mostrar una vez, como mensajes de éxito o error tras enviar un formulario.

### Guardar con `flash()`

```php theme={null}
$request->session()->flash('status', 'Post guardado.');
```

Los datos pueden leerse en la siguiente solicitud, tras la cual se eliminan automáticamente.

### Extender datos flash

```php theme={null}
// Extiende todos los datos flash una solicitud más
$request->session()->reflash();

// Extiende solo ciertas claves
$request->session()->keep(['status', 'message']);
```

### Mostrar mensajes flash en Blade

```blade theme={null}
{{-- resources/views/layouts/app.blade.php --}}

@if (session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif

@if (session('error'))
    <div class="alert alert-danger">
        {{ session('error') }}
    </div>
@endif
```

<Tip>
  Escribir la visualización del mensaje flash en el layout (por ejemplo `layouts/app.blade.php`) permite mostrarlo de forma consistente en todas las páginas.
</Tip>

## Caso práctico: mostrar mensaje tras enviar un formulario

Guardar un mensaje de éxito en la sesión, hacer un redirect y mostrarlo en la siguiente página es un patrón clásico.

<Steps>
  <Step title="Definir las rutas">
    ```php theme={null}
    use App\Http\Controllers\PostController;

    Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
    Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create');
    Route::post('/posts', [PostController::class, 'store'])->name('posts.store');
    ```
  </Step>

  <Step title="Implementar el controlador">
    En el `store` que recibe el formulario, tras guardar redirige con un mensaje de éxito.

    ```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
    {
        public function index(): View
        {
            $posts = Post::latest()->get();

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

        public function create(): View
        {
            return view('posts.create');
        }

        public function store(Request $request): RedirectResponse
        {
            $validated = $request->validate([
                'title' => 'required|string|max:255',
                'body'  => 'required|string',
            ]);

            Post::create($validated);

            return redirect()
                ->route('posts.index')
                ->with('success', 'Post creado.');
        }
    }
    ```

    `redirect()->with('success', '...')` es un atajo para pasar datos flash al destino de la redirección.
  </Step>

  <Step title="Mostrar el mensaje en el layout">
    Añade la visualización del mensaje flash en `resources/views/layouts/app.blade.php`.

    ```blade theme={null}
    <!DOCTYPE html>
    <html>
    <head>
        <title>My App</title>
    </head>
    <body>
        {{-- Mensajes flash --}}
        @if (session('success'))
            <div class="alert alert-success">
                {{ session('success') }}
            </div>
        @endif

        @if (session('error'))
            <div class="alert alert-danger">
                {{ session('error') }}
            </div>
        @endif

        @yield('content')
    </body>
    </html>
    ```
  </Step>

  <Step title="Crear la vista del listado">
    ```blade theme={null}
    {{-- resources/views/posts/index.blade.php --}}

    @extends('layouts.app')

    @section('content')
    <h1>Lista de posts</h1>

    @foreach ($posts as $post)
        <div>
            <h2>{{ $post->title }}</h2>
            <p>{{ $post->body }}</p>
        </div>
    @endforeach
    @endsection
    ```

    Al guardar el post y redirigir, en la parte superior del listado se mostrará una vez el mensaje "Post creado.".
  </Step>
</Steps>

### Patrón combinado con errores de validación

En caso de fallo de validación se combina con `back()->withErrors()`.
Laravel guarda automáticamente los errores como datos flash, así que en Blade puedes usar la variable `$errors`.

```php theme={null}
public function store(Request $request): RedirectResponse
{
    $validated = $request->validate([
        'title' => 'required|string|max:255',
        'body'  => 'required|string',
    ]);

    Post::create($validated);

    // Éxito: redirige con mensaje flash
    return redirect()
        ->route('posts.index')
        ->with('success', 'Post creado.');

    // En caso de fallo de validación Laravel ejecuta automáticamente back()->withErrors()->withInput()
}
```

```blade theme={null}
{{-- Página del formulario --}}

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<form method="POST" action="{{ route('posts.store') }}">
    @csrf

    <div>
        <label for="title">Título</label>
        <input
            id="title"
            type="text"
            name="title"
            value="{{ old('title') }}"
        />
        @error('title')
            <span>{{ $message }}</span>
        @enderror
    </div>

    <div>
        <label for="body">Contenido</label>
        <textarea id="body" name="body">{{ old('body') }}</textarea>
        @error('body')
            <span>{{ $message }}</span>
        @enderror
    </div>

    <button type="submit">Publicar</button>
</form>
```

<Warning>
  `flush()` elimina todos los datos de la sesión, incluido el estado de autenticación. Si solo quieres eliminar datos específicos, usa `forget()` indicando la clave.
</Warning>

## Próximos pasos

<Card title="Validación" icon="check-circle" href="/es/validation">
  Aprende a validar los datos introducidos en un formulario.
</Card>


## Related topics

- [Reanudar sesión](/es/packages/laravel-copilot-sdk/resume.md)
- [Hooks de sesión](/es/packages/laravel-copilot-sdk/hooks.md)
- [Contexto de sesión y filtrado](/es/packages/laravel-copilot-sdk/session-context.md)
- [Eventos del ciclo de vida de sesión](/es/packages/laravel-copilot-sdk/session-lifecycle-event.md)
- [Pruebas HTTP](/es/http-tests.md)
