Flash Messages in Slim 4 Framework
What are Flash Messages?
Section titled “What are Flash Messages?”Flash messages are short-lived messages that provide user feedback after form submissions or actions (such as item deletion, form validation errors, etc.).
- How it works? When a user logs in, registers, or updates their profile, you redirect them to another page and show a message like “Login successful!” or “Profile updated!”
- Flash messages are stored in the session, survive one redirect, and then might automatically disappear.
Common use cases:
- ✅ Success: “Login successful!” or “Profile updated!”
- ✅ Error: “Invalid password” or “Email already exists”
- ✅ Info: “Check your email for verification link”
- ✅ Warning: “Your session will expire in 5 minutes”
Creating the FlashMessage Class
Section titled “Creating the FlashMessage Class”The FlashMessage class is a wrapper class that will help us manage flash messages in our application by providing a clean API for managing messages.
This class needs to be created in the app/Helpers/FlashMessage.php file.
<?php
namespace App\Helpers;
class FlashMessage{    private const FLASH_KEY = 'flash_messages';
    /**     * Add a success message.     */    public static function success(string $message): void    {        self::add('success', $message);    }
    /**     * Add an error message.     */    public static function error(string $message): void    {        self::add('error', $message);    }
    /**     * Add an info message.     */    public static function info(string $message): void    {        self::add('info', $message);    }
    /**     * Add a warning message.     */    public static function warning(string $message): void    {        self::add('warning', $message);    }
    /**     * Add a flash message of any type.     */    public static function add(string $type, string $message): void    {        if (!isset($_SESSION[self::FLASH_KEY])) {            $_SESSION[self::FLASH_KEY] = [];        }
        $_SESSION[self::FLASH_KEY][] = [            'type' => $type,            'message' => $message        ];    }
    /**     * Get all flash messages and clear them.     */    public static function get(): array    {        $messages = $_SESSION[self::FLASH_KEY] ?? [];        unset($_SESSION[self::FLASH_KEY]);        return $messages;    }
    /**     * Check if there are any flash messages.     */    public static function has(): bool    {        return !empty($_SESSION[self::FLASH_KEY]);    }
    /**     * Clear all flash messages without retrieving them.     */    public static function clear(): void    {        unset($_SESSION[self::FLASH_KEY]);    }
    /**     * Render all flash messages as Bootstrap alerts.     */    public static function render(bool $dismissible = true): string    {        $messages = self::get();        if (empty($messages)) {            return '';        }
        $bootstrapTypes = [            'success' => 'success',            'error' => 'danger',            'info' => 'info',            'warning' => 'warning'        ];
        $html = '';        foreach ($messages as $flash) {            $type = $bootstrapTypes[$flash['type']] ?? 'info';            $message = htmlspecialchars($flash['message']);
            if ($dismissible) {                $html .= <<<HTML                <div class="alert alert-{$type} alert-dismissible fade show" role="alert">                    {$message}                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>                </div>                HTML;            } else {                $html .= <<<HTML                <div class="alert alert-{$type}" role="alert">                    {$message}                </div>                HTML;            }        }
        return $html;    }}FlashMessage Class Methods
Section titled “FlashMessage Class Methods”Here is a list of the methods available in the FlashMessage class.
| Method | Description | 
|---|---|
| FlashMessage::success($msg) | Add a success message | 
| FlashMessage::error($msg) | Add an error message (displays as Bootstrap alert-danger) | 
| FlashMessage::info($msg) | Add an info message | 
| FlashMessage::warning($msg) | Add a warning message | 
| FlashMessage::add($type, $msg) | Add a custom message type | 
| FlashMessage::render($dismissible) | Display all messages as Bootstrap alerts (dismissible by default) | 
| FlashMessage::get() | Retrieve and clear all messages (auto-cleanup) | 
| FlashMessage::has() | Check if messages exist | 
| FlashMessage::clear() | Clear all messages without retrieving them | 
Using Flash Messages in Routes
Section titled “Using Flash Messages in Routes”Using the FlashMessage::add($type, $message) method
Section titled “Using the FlashMessage::add($type, $message) method”To set a flash message, we can use the FlashMessage::add($type, $message) method.
This method takes two parameters:
- $type: The type of message to add. This can be- success,- error,- info, or- warning.
- $message: The message to add.
FlashMessage::add('success', 'Login successful! Welcome back.');FlashMessage::add('error', 'Invalid password. Please try again.');FlashMessage::add('info', 'Check your email for verification link.');FlashMessage::add('warning', 'Your session will expire in 5 minutes.');
// redirect to the dashboard (or any other view).return $response->withHeader('Location', '/dashboard')->withStatus(302);Using the FlashMessage class’s proxy methods
Section titled “Using the FlashMessage class’s proxy methods”Or any of the other methods like success($message), error($message), info($message), warning($message) as shown in the example below.
use App\Helpers\FlashMessage;
// After successful login, we add a success message and redirect to the dashboard.$app->post('/login', function ($request, $response) {    // ... validate credentials ...
    FlashMessage::success('Login successful! Welcome back.');
    return $response->withHeader('Location', '/dashboard')->withStatus(302);});
// After registration fails, we add an error message and redirect to the registration page.$app->post('/register', function ($request, $response) {    // ... validation fails ...
    FlashMessage::error('Email already exists. Please use a different email.');
    return $response->withHeader('Location', '/register')->withStatus(302);});
// Multiple types can be added to the same message. We add a success message and an info message and redirect to the profile page.$app->post('/update-profile', function ($request, $response) {    FlashMessage::success('Profile updated successfully!');    FlashMessage::info('Changes will appear within 24 hours.');
    return $response->withHeader('Location', '/profile')->withStatus(302);});Displaying Flash Messages in Views
Section titled “Displaying Flash Messages in Views”Using render() Method (Recommended)
Section titled “Using render() Method (Recommended)”The simplest way to display flash messages in your views is to use the FlashMessage::render() method.
<?= App\Helpers\FlashMessage::render() ?>That’s it! This will automatically:
- Retrieve and display all flash messages
- Map types to Bootstrap classes (error→alert-danger)
- Create dismissible alerts with close buttons
- Clear messages after display
- HTML-escape messages for security
Non-dismissible alerts:
<?= App\Helpers\FlashMessage::render(false) ?>or:
<?php if (FlashMessage::has()): ?>    <?php echo FlashMessage::render(); ?><?php endif; ?>Manual Rendering (Alternative)
Section titled “Manual Rendering (Alternative)”If you need custom styling, you can manually render:
<?phpuse App\Helpers\FlashMessage;
$messages = FlashMessage::get();$bootstrapTypes = [    'success' => 'success',    'error' => 'danger',    'info' => 'info',    'warning' => 'warning'];?>
<?php foreach ($messages as $flash): ?>    <?php $type = $bootstrapTypes[$flash['type']] ?? 'info'; ?>    <div class="alert alert-<?= $type ?>" role="alert">        <?= htmlspecialchars($flash['message']) ?>    </div><?php endforeach; ?>Common Patterns
Section titled “Common Patterns”The following are some common patterns for using flash messages in your application.
Pattern 1: Form Validation Errors
Section titled “Pattern 1: Form Validation Errors”$app->post('/contact', function ($request, $response) {    $data = $request->getParsedBody();
    if (empty($data['email'])) {        FlashMessage::error('Email is required.');        return $response->withHeader('Location', '/contact')->withStatus(302);    }
    if (empty($data['message'])) {        FlashMessage::error('Message cannot be empty.');        return $response->withHeader('Location', '/contact')->withStatus(302);    }
    // Process form...    FlashMessage::success('Message sent successfully!');    return $response->withHeader('Location', '/')->withStatus(302);});Pattern 2: CRUD Operations
Section titled “Pattern 2: CRUD Operations”// Create$app->post('/products', function ($request, $response) {    // ... create product ...    FlashMessage::success('Product created successfully!');    return $response->withHeader('Location', '/products')->withStatus(302);});
// Update$app->put('/products/{id}', function ($request, $response, $args) {    // ... update product ...    FlashMessage::info('Product updated.');    return $response->withHeader('Location', '/products')->withStatus(302);});
// Delete$app->delete('/products/{id}', function ($request, $response, $args) {    // ... delete product ...    FlashMessage::warning('Product deleted.');    return $response->withHeader('Location', '/products')->withStatus(302);});Pattern 3: Multi-Step Forms
Section titled “Pattern 3: Multi-Step Forms”$app->post('/checkout/step-1', function ($request, $response) {    // ... save shipping info ...    FlashMessage::success('Shipping information saved.');    return $response->withHeader('Location', '/checkout/step-2')->withStatus(302);});
$app->post('/checkout/step-2', function ($request, $response) {    // ... save payment info ...    FlashMessage::success('Payment method saved.');    return $response->withHeader('Location', '/checkout/confirm')->withStatus(302);});Best Practices
Section titled “Best Practices”1. Always Redirect After Setting Flash
Section titled “1. Always Redirect After Setting Flash”// ✅ Good - redirect after flash messageFlashMessage::success('Saved!');return $response->withHeader('Location', '/dashboard')->withStatus(302);
// ❌ Bad - no redirect (message won't display properly)FlashMessage::success('Saved!');return $response->getBody()->write('Done');2. Use Appropriate Message Types
Section titled “2. Use Appropriate Message Types”// ✅ Good - clear message typesFlashMessage::success('Account created successfully!');FlashMessage::error('Password is too weak.');FlashMessage::warning('Trial period ending soon.');FlashMessage::info('New features available.');
// ❌ Bad - wrong typeFlashMessage::success('Error: Login failed!'); // Should be error()3. Keep Messages Short and Clear
Section titled “3. Keep Messages Short and Clear”// ✅ Good - concise and clearFlashMessage::success('Profile updated!');FlashMessage::error('Invalid email address.');
// ❌ Bad - too verboseFlashMessage::success('Your profile has been successfully updated and all changes have been saved to the database.');Quick Reference
Section titled “Quick Reference”Setting messages in routes:
use App\Helpers\FlashMessage;
FlashMessage::success('Success message');FlashMessage::error('Error message');FlashMessage::info('Info message');FlashMessage::warning('Warning message');FlashMessage::add('custom', 'Custom type message');Displaying in views (Recommended):
<?= App\Helpers\FlashMessage::render() ?>              // Dismissible alerts<?= App\Helpers\FlashMessage::render(false) ?>         // Non-dismissibleOther methods:
// Check if messages existif (FlashMessage::has()) {    // Messages available}
// Get messages manually (auto-clears)$messages = FlashMessage::get();
// Clear without retrievingFlashMessage::clear();Things to Remember
Section titled “Things to Remember”- ✅ Flash messages are one-time, temporary messages
- ✅ FlashMessageclass provides clean API for managing messages
- ✅ Four built-in types: success, error, info, warning
- ✅ Use FlashMessage::render()for one-line display in views
- ✅ Messages auto-clear after display
- ✅ Always redirect after setting flash messages
- ✅ Bootstrap uses alert-dangerfor error messages (notalert-error)