Flash Messages Lab
Additional Resources
Section titled “Additional Resources”Flash Instructions: Implementing Flash Messages
Section titled “Flash Instructions: Implementing Flash Messages”In this lab, you will implement a flash messaging system for your Slim 4 application. Flash messages provide temporary user feedback after form submissions, login attempts, and other actions. By the end of this lab, you’ll have a fully functional flash messaging system using Bootstrap alerts.
Learning Objectives
Section titled “Learning Objectives”By completing this lab, you will:
- Understand what flash messages are and when to use them.
- Create a FlashMessage helper class for managing temporary messages.
- Integrate flash messages with the BaseController redirect() method.
- Display flash messages in views using Bootstrap alerts.
- Implement the Post-Redirect-Get (PRG) pattern correctly.
- Handle success, error, info, and warning messages.
Prerequisites
Section titled “Prerequisites”Before starting this lab, ensure you have:
- Completed the Session Middleware lab (flash messages require sessions).
- A working Slim 4 application with SessionMiddleware registered
- Basic understanding of the BaseController pattern.
- Bootstrap CSS included in your views (for styled alerts).
- Your development environment set up and running.
Lab Steps
Section titled “Lab Steps”Step 1: Create the FlashMessage Helper Class
Section titled “Step 1: Create the FlashMessage Helper Class”Objective: Create a helper class that manages flash messages stored in the session.
Instructions:
- Navigate to your app/Helpers/directory
- Create a new file named FlashMessage.php
- Copy and paste the following code:
<?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;    }}- Save the file
What you just created:
- A FlashMessage helper class with methods for different message types
- Methods to add, retrieve, check, and clear flash messages
- A render()method that automatically generates Bootstrap alert HTML
- Automatic message cleanup after display
- XSS protection with htmlspecialchars()
Step 2: Create a Test Controller
Section titled “Step 2: Create a Test Controller”Objective: Create a controller to demonstrate flash message functionality.
Instructions:
- Navigate to your app/Controllers/directory
- Create a new file named FlashDemoController.php
- Implement a controller class that extends BaseControllerwith the following requirements:
Class Structure:
<?php
namespace App\Controllers;
use App\Helpers\FlashMessage;use DI\Container;use Psr\Http\Message\ResponseInterface as Response;use Psr\Http\Message\ServerRequestInterface as Request;
class FlashDemoController extends BaseController{    public function __construct(Container $container)    {        parent::__construct($container);    }
    // TODO: Implement the methods below}Controller callback methods to implement:
Create the following public controller callback methods. Each controller callback method should:
- Accept the standard Slim framework callback method parameters: Request $request, Response $response, array $args
- Return a Responseobject
| Callback Method Name | What It Should Do | 
|---|---|
| index() | Render the flash/flashIndexView.phpview with a title “Flash Messages Demo” | 
| success() | Add a success flash message, then redirect to the flash.demoroute | 
| error() | Add an error flash message, then redirect to the flash.demoroute | 
| info() | Add an info flash message, then redirect to the flash.demoroute | 
| warning() | Add a warning flash message, then redirect to the flash.demoroute | 
| multiple() | Add 2-3 flash messages of different types, then redirect to the flash.demoroute | 
Implementation Hints:
Click to see hints for implementing the methods
For the index() method:
public function index(Request $request, Response $response, array $args): Response{    // Use $this->render() to render the view    // Pass 'title' in the data array}For message methods (success(), error(), etc.):
public function success(Request $request, Response $response, array $args): Response{    // 1. Use FlashMessage::success() to add a message    // 2. Use $this->redirect() to redirect to 'flash.demo' route}For the multiple() method:
public function multiple(Request $request, Response $response, array $args): Response{    // 1. Call FlashMessage::success() with a message    // 2. Call FlashMessage::info() with a different message    // 3. Call FlashMessage::warning() with another message    // 4. Use $this->redirect() to redirect to 'flash.demo' route}Key Points to Remember:
- Use FlashMessage::success(),FlashMessage::error(),FlashMessage::info(), orFlashMessage::warning()
- Always use $this->redirect($request, $response, 'route.name')after setting flash messages
- The message text can be anything descriptive (e.g., “This is a success message!”)
- For multiple(), demonstrate that you can set multiple messages before redirecting
- Save the file
What you should have created:
- A controller extending BaseController with a constructor
- An index()method that renders a view
- Five methods that set flash messages and redirect
- Proper use of the Post-Redirect-Get (PRG) pattern
Step 3: Register Routes
Section titled “Step 3: Register Routes”Objective: Add routes for the flash message demo controller.
Instructions:
- Open your app/Routes/web-routes.phpfile
- Add the following import at the top:
use App\Controllers\FlashDemoController;- Add these routes:
// Flash message demo routes$app->get('/flash', [FlashDemoController::class, 'index'])->setName('flash.demo');$app->post('/flash/success', [FlashDemoController::class, 'success'])->setName('flash.success');$app->post('/flash/error', [FlashDemoController::class, 'error'])->setName('flash.error');$app->post('/flash/info', [FlashDemoController::class, 'info'])->setName('flash.info');$app->post('/flash/warning', [FlashDemoController::class, 'warning'])->setName('flash.warning');$app->post('/flash/multiple', [FlashDemoController::class, 'multiple'])->setName('flash.multiple');- Save the file
Step 4: Create the Demo View
Section titled “Step 4: Create the Demo View”Objective: Create a view that displays flash messages and provides buttons to test each message type.
Instructions:
- Navigate to your views/directory
- Create a new folder named flash/
- Inside flash/, create a file namedflashIndexView.php
- Copy and paste the following code:
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title><?= htmlspecialchars($title ?? 'Flash Demo') ?></title>    <!-- Bootstrap 5 CSS -->    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"></head><body>    <div class="container mt-5">        <h1 class="mb-4"><?= htmlspecialchars($title ?? 'Flash Demo') ?></h1>
        <!-- Flash Messages Display Area -->        <div class="mb-4">            <?= App\Helpers\FlashMessage::render() ?>        </div>
        <div class="card">            <div class="card-header">                <h5>Test Flash Messages</h5>            </div>            <div class="card-body">                <p class="card-text">Click the buttons below to test different types of flash messages:</p>
                <div class="d-grid gap-2">                    <form method="POST" action="flash/success">                        <button type="submit" class="btn btn-success w-100">                            Show Success Message                        </button>                    </form>
                    <form method="POST" action="flash/error">                        <button type="submit" class="btn btn-danger w-100">                            Show Error Message                        </button>                    </form>
                    <form method="POST" action="flash/info">                        <button type="submit" class="btn btn-info w-100">                            Show Info Message                        </button>                    </form>
                    <form method="POST" action="flash/warning">                        <button type="submit" class="btn btn-warning w-100">                            Show Warning Message                        </button>                    </form>
                    <form method="POST" action="flash/multiple">                        <button type="submit" class="btn btn-primary w-100">                            Show Multiple Messages                        </button>                    </form>                </div>            </div>        </div>
        <div class="alert alert-info mt-4" role="alert">            <strong>Note:</strong> Flash messages appear once and then disappear. Refresh the page to clear any visible messages.        </div>    </div>
    <!-- Bootstrap 5 JS -->    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script></body></html>- Save the file
What you just created:
- A view that displays flash messages using FlashMessage::render()
- Buttons to test each message type
- Bootstrap-styled layout
- Forms using POST method to demonstrate PRG pattern
Step 5: Test Your Implementation
Section titled “Step 5: Test Your Implementation”Objective: Verify that flash messages work correctly.
Instructions:
- Start your development server (if not already running)
- Visit http://localhost/[your-app-name]/flashin your browser
- Click each button and observe the flash messages:
- “Show Success Message” → Green alert
- “Show Error Message” → Red alert
- “Show Info Message” → Blue alert
- “Show Warning Message” → Yellow alert
- “Show Multiple Messages” → Three different alerts
 
Expected Behavior:
- ✅ Messages appear at the top of the page after redirect
- ✅ Messages have appropriate colors (success=green, error=red, etc.)
- ✅ Messages have close buttons (dismissible)
- ✅ Refreshing the page clears all messages
- ✅ Multiple messages can be displayed at once
If messages don’t appear:
- Verify SessionMiddleware is registered in config/middleware.php
- Check browser console for JavaScript errors
- Ensure Bootstrap CSS and JS are loading
- Verify the FlashMessage::render() line is in your view
Verification Checklist
Section titled “Verification Checklist”Before submitting your lab, verify the following:
-  FlashMessage.php exists in app/Helpers/directory
-  FlashDemoController.php exists in app/Controllers/directory
-  All six controller methods are implemented correctly (index,success,error,info,warning,multiple)
-  Flash demo routes are registered in web-routes.php
-  Flash demo page (/flash) displays all message types correctly
- Messages disappear after page refresh
- Multiple messages can be displayed simultaneously
- Close buttons work on dismissible alerts
Understanding What You Built
Section titled “Understanding What You Built”FlashMessage Helper Methods
Section titled “FlashMessage Helper Methods”| Method | Description | Example | 
|---|---|---|
| success($msg) | Add a success message (green alert) | FlashMessage::success('Saved!') | 
| error($msg) | Add an error message (red alert) | FlashMessage::error('Invalid input') | 
| info($msg) | Add an info message (blue alert) | FlashMessage::info('Check your email') | 
| warning($msg) | Add a warning message (yellow alert) | FlashMessage::warning('Trial ending soon') | 
| add($type, $msg) | Add a custom message type | FlashMessage::add('custom', 'Message') | 
| render($dismissible) | Display all messages as Bootstrap alerts | <?= FlashMessage::render() ?> | 
| get() | Retrieve and clear all messages | $messages = FlashMessage::get() | 
| has() | Check if messages exist | if (FlashMessage::has()) | 
| clear() | Clear all messages without retrieving | FlashMessage::clear() | 
How Flash Messages Work
Section titled “How Flash Messages Work”- Setting: Flash message is stored in $_SESSION['flash_messages']
- Redirect: User is redirected to another page (PRG pattern)
- Display: Next page renders messages using FlashMessage::render()
- Auto-clear: Messages are automatically removed after being retrieved
- Result: Message only appears once, then disappears
Bootstrap Alert Mapping
Section titled “Bootstrap Alert Mapping”| Flash Type | Bootstrap Class | Color | 
|---|---|---|
| success | alert-success | Green | 
| error | alert-danger | Red | 
| info | alert-info | Blue | 
| warning | alert-warning | Yellow | 
Common Issues and Solutions
Section titled “Common Issues and Solutions”Issue 1: Messages Don’t Appear
Section titled “Issue 1: Messages Don’t Appear”Cause: SessionMiddleware not registered or sessions not working
Solution:
- Verify SessionMiddlewareis inconfig/middleware.php
- Test that sessions work with the /test-sessionroute
- Check browser accepts cookies
Issue 2: Messages Appear Multiple Times
Section titled “Issue 2: Messages Appear Multiple Times”Cause: Calling FlashMessage::render() multiple times
Solution:
- Only call render()once per page
- Check your layout/view for duplicate calls
Issue 3: Messages Persist After Refresh
Section titled “Issue 3: Messages Persist After Refresh”Cause: render() not being called, so messages aren’t cleared
Solution:
- Ensure FlashMessage::render()is in your view
- Alternatively, call FlashMessage::get()orclear()manually
Issue 4: Bootstrap Styles Not Showing
Section titled “Issue 4: Bootstrap Styles Not Showing”Cause: Bootstrap CSS not loaded
Solution:
- Add Bootstrap CDN link to your view’s <head>:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">