Lección 27 de 45 10 min de lectura

Mensajes flash

Los mensajes flash son notificaciones temporales que se muestran al usuario después de una acción: "Usuario creado correctamente", "Error al guardar", etc. Laravel almacena estos mensajes en la sesión y los elimina automáticamente tras mostrarlos.

¿Qué son los mensajes flash?

Los mensajes flash son datos que se guardan en la sesión solo para la siguiente petición. Son perfectos para:

  • Confirmar que una acción se completó correctamente
  • Mostrar errores que no son de validación
  • Informar al usuario de cambios importantes

A diferencia de los errores de validación (que vimos en lecciones anteriores), los mensajes flash son genéricos y los controlas tú completamente.

Enviar mensajes flash

La forma más común es usar el método with() en una redirección:

php
<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
        ]);

        User::create($validated);

        return redirect()
            ->route('users.index')
            ->with('success', 'Usuario creado correctamente.');
    }
}

El método with('clave', 'valor') guarda el mensaje en la sesión. La clave puede ser cualquier nombre: success, error, info, warning, etc.

Mostrar mensajes en Blade

Laravel ofrece la directiva @session para mostrar mensajes flash de forma elegante. Si el valor existe, se muestra el contenido y puedes usar $value para acceder al mensaje:

blade
{{-- resources/views/users/index.blade.php --}}

@session('success')
    <div class="alert alert-success">
        {{ $value }}
    </div>
@endsession

@session('error')
    <div class="alert alert-danger">
        {{ $value }}
    </div>
@endsession

{{-- Resto de la vista --}}

También puedes usar la sintaxis tradicional con @if y el helper session():

blade
@if(session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif
Solo una petición

Los mensajes flash solo existen para la siguiente petición. Si el usuario recarga la página, el mensaje desaparece automáticamente.

Tipos de mensajes comunes

Es buena práctica usar nombres consistentes para los tipos de mensaje:

php
<?php

// Éxito - acción completada correctamente
return redirect()->route('users.index')
    ->with('success', 'Usuario creado correctamente.');

// Error - algo salió mal
return redirect()->route('users.index')
    ->with('error', 'No se pudo eliminar el usuario.');

// Información - mensaje neutral
return redirect()->route('dashboard')
    ->with('info', 'Tu sesión se cerrará en 5 minutos.');

// Advertencia - precaución
return redirect()->route('settings.index')
    ->with('warning', 'Algunos cambios requieren reiniciar.');

Múltiples mensajes flash

Puedes encadenar varios mensajes con with():

php
<?php

return redirect()->route('users.index')
    ->with('success', 'Usuario creado.')
    ->with('info', 'Se ha enviado un email de bienvenida.');

O usar un array:

php
<?php

return redirect()->route('users.index')->with([
    'success' => 'Usuario creado.',
    'info' => 'Se ha enviado un email de bienvenida.',
]);

Usando el facade Session

También puedes usar directamente el facade Session para más control:

php
<?php

use Illuminate\Support\Facades\Session;

// Guardar mensaje flash
Session::flash('success', 'Operación completada.');

// También disponible con el helper session()
session()->flash('success', 'Operación completada.');

// Mantener mensajes flash para otra petición más
Session::reflash();

// Mantener solo ciertos mensajes
Session::keep(['success', 'info']);

Componente reutilizable para alertas

Para evitar repetir código, crea un componente Blade que muestre todas las alertas:

blade
{{-- resources/views/components/alerts.blade.php --}}

@session('success')
    <div class="alert alert-success">{{ $value }}</div>
@endsession

@session('error')
    <div class="alert alert-danger">{{ $value }}</div>
@endsession

@session('warning')
    <div class="alert alert-warning">{{ $value }}</div>
@endsession

@session('info')
    <div class="alert alert-info">{{ $value }}</div>
@endsession

Luego inclúyelo en tu layout principal:

blade
{{-- resources/views/layouts/app.blade.php --}}

<body>
    <x-alerts />

    <main>
        {{ $slot }}
    </main>
</body>

Ejemplo completo: CRUD con mensajes

Veamos un controlador CRUD completo con mensajes flash:

php
<?php

declare(strict_types=1);

namespace App\Http\Controllers;

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

class ArticleController extends Controller
{
    public function index(): View
    {
        $articles = Article::latest()->paginate(10);

        return view('articles.index', compact('articles'));
    }

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

        Article::create($validated);

        return redirect()
            ->route('articles.index')
            ->with('success', 'Artículo creado correctamente.');
    }

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

        $article->update($validated);

        return redirect()
            ->route('articles.index')
            ->with('success', 'Artículo actualizado correctamente.');
    }

    public function destroy(Article $article): RedirectResponse
    {
        $article->delete();

        return redirect()
            ->route('articles.index')
            ->with('success', 'Artículo eliminado correctamente.');
    }
}

Mensajes flash con datos adicionales

A veces necesitas pasar más que un simple texto. Puedes guardar arrays u objetos:

php
<?php

// Guardar un array con tipo y mensaje
return redirect()->route('orders.index')->with('notification', [
    'type' => 'success',
    'title' => 'Pedido confirmado',
    'message' => 'Tu pedido #' . $order->id . ' ha sido procesado.',
]);
blade
@if(session('notification'))
    @php $notification = session('notification'); @endphp
    <div class="alert alert-{{ $notification['type'] }}">
        <strong>{{ $notification['title'] }}</strong>
        <p>{{ $notification['message'] }}</p>
    </div>
@endif

Redirección con errores personalizados

El método withErrors() permite enviar errores que se muestran igual que los de validación:

php
<?php

public function processPayment(Request $request): RedirectResponse
{
    // Simular error de pago externo
    $paymentSuccessful = false;

    if (! $paymentSuccessful) {
        return redirect()
            ->back()
            ->withErrors(['payment' => 'El pago no pudo procesarse.'])
            ->withInput();
    }

    return redirect()->route('orders.success');
}
blade
@error('payment')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

Resumen

  • Los mensajes flash viven solo una petición
  • redirect()->with('clave', 'mensaje') envía un mensaje
  • @session('clave') muestra el mensaje con $value
  • También puedes usar session('clave') con @if
  • Usa nombres consistentes: success, error, info, warning
  • Crea un componente reutilizable para mostrar alertas
  • Session::flash() permite más control
  • Session::reflash() mantiene los mensajes una petición más
  • withErrors() envía errores personalizados

Ejercicios

Ejercicio 1: Mensajes en un controlador de tareas

Crea un controlador TaskController con métodos store, update y destroy. Cada método debe redirigir a tasks.index con un mensaje de éxito apropiado.

Ver solución
<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Task;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

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

        Task::create($validated);

        return redirect()
            ->route('tasks.index')
            ->with('success', 'Tarea creada correctamente.');
    }

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

        $task->update($validated);

        return redirect()
            ->route('tasks.index')
            ->with('success', 'Tarea actualizada correctamente.');
    }

    public function destroy(Task $task): RedirectResponse
    {
        $task->delete();

        return redirect()
            ->route('tasks.index')
            ->with('success', 'Tarea eliminada correctamente.');
    }
}

Ejercicio 2: Componente de alertas con iconos

Crea un componente Blade x-alert que reciba un parámetro type (success, error, warning, info) y muestre un icono diferente según el tipo. El mensaje se pasa como slot.

Ver solución
{{-- resources/views/components/alert.blade.php --}}

@props(['type' => 'info'])

@php
    $icons = [
        'success' => '✓',
        'error' => '✕',
        'warning' => '⚠',
        'info' => 'ℹ',
    ];
    $icon = $icons[$type] ?? $icons['info'];
@endphp

<div {{ $attributes->merge(['class' => 'alert alert-' . $type]) }}>
    <span class="alert-icon">{{ $icon }}</span>
    <span class="alert-message">{{ $slot }}</span>
</div>

{{-- Uso: --}}
{{-- <x-alert type="success">Usuario creado.</x-alert> --}}

Ejercicio 3: Múltiples mensajes flash

En un controlador, después de procesar una compra, envía dos mensajes flash: uno de éxito con "Compra realizada" y otro de información con "Recibirás un email de confirmación". Luego escribe el código Blade para mostrar ambos mensajes.

Ver solución
<?php

// En el controlador
public function completePurchase(Request $request): RedirectResponse
{
    // Procesar la compra...

    return redirect()
        ->route('orders.index')
        ->with('success', 'Compra realizada correctamente.')
        ->with('info', 'Recibirás un email de confirmación.');
}
{{-- En la vista --}}

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

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

¿Te está gustando el curso?

Tenemos cursos premium con proyectos reales, soporte personalizado y certificado.

Descubrir cursos premium