Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Flash Alert Bundle Laravel Package

edinchev/flash-alert-bundle

A Laravel bundle for rendering flash alert messages in your application. Provides a simple way to queue and display success, error, warning, and info notifications across redirects and requests, with Blade views for consistent, customizable alert output.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: edinchev/flash-alert-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/flash-alert.php, and Composer auto-discovery will do nothing for you. So "getting started" splits into two tracks depending on what you're actually doing.

Track A — You're working in a Symfony app

  1. Install:
    composer require edinchev/flash-alert-bundle
    
  2. Register the bundle:
    • Symfony 3 and older: add to app/AppKernel.php → registerBundles().
    • Symfony 4+: add to config/bundles.php:
      Edinchev\FlashAlertBundle\FlashAlertBundle::class => ['all' => true],
      
  3. Look first at these files in the repo, in this order:
    • composer.json — tells you which Symfony versions are actually supported. This is your go/no-go gate.
    • Resources/views/ — the Twig template you'll {% include %} in your base layout.
    • Resources/public/js/ — the pure-JS renderer. Read it before trusting it; it defines the DOM contract and any globals it expects.
    • The service class (usually under Services/ or FlashAlert.php) — this is your public API surface.
  4. First use case: flash a success message after a form submit and render it once at the top of the page.
    // Controller
    $this->get('flash_alert')->success('Saved.'); // or constructor-inject the service
    return $this->redirectToRoute('dashboard');
    
    {# base.html.twig #}
    {% include 'FlashAlertBundle::flash.html.twig' %}
    
    Plus the JS/CSS from the bundle's Resources/public directory wired into your asset pipeline.

Track B — You're a Laravel developer evaluating this

Don't install it. The bundle's value is roughly 150 lines of logic plus a small DOM renderer, and all of it is trivially reproducible in Laravel with session()->flash() and any toast library (Notyf, Toastr, or a 40-line Alpine component). The only reason to open the repo is to steal the integration pattern, not the code.

Equivalent Laravel skeleton:

// app/Support/Flash.php
class Flash
{
    public static function success(string $msg): void { session()->flash('flash', ['type' => 'success', 'message' => $msg]); }
    public static function error(string $msg): void   { session()->flash('flash', ['type' => 'danger',  'message' => $msg]); }
}
{{-- resources/views/partials/flash.blade.php --}}
@if (session('flash'))
    <div class="alert alert-{{ session('flash.type') }}" data-flash>{{ session('flash.message') }}</div>
@endif

That is the whole package, in a form you can debug.


Implementation Patterns

Pattern 1 — Service injection, not container lookups

The bundle exposes a service (flash_alert in Symfony 2/3 style). In modern Symfony you constructor-inject it; in Laravel terms this is exactly like injecting a FlashService instead of calling session() from twelve places.

final class OrderController
{
    public function __construct(private FlashAlert $flash) {}

    public function store(StoreOrder $request)
    {
        $order = Order::create($request->validated());
        $this->flash->success("Order #{$order->id} created.");
        return $this->redirectToRoute('orders.index');
    }
}

Why this matters day-to-day: it gives you one seam to intercept. In a Laravel port, that same seam lets you swap in a queue-backed or Livewire-broadcast flash without touching controllers.

Pattern 2 — Render once, in the base layout, and nowhere else

The single most common failure mode with any flash package is double rendering: the layout includes the partial, and an AJAX-loaded fragment also includes it. Define the contract explicitly:

  • Full page render → layout partial emits the container.
  • AJAX/fragment render → fragment returns data only, and the client-side JS appends it.
{# Only in the base layout, guarded so partials can opt out #}
{% block flash %}{% include 'FlashAlertBundle::flash.html.twig' %}{% endblock %}
{{-- Laravel equivalent: guard with a view-share flag --}}
@unless($__env->yieldContent('suppressFlash'))
    @include('partials.flash')
@endunless

Pattern 3 — Map domain outcomes to a fixed vocabulary

The bundle ships with the usual success / info / warning / error types. Resist adding a fifth one until you've checked that your CSS and JS actually handle it — the renderer typically has a hardcoded class map.

enum FlashLevel: string {
    case Success = 'success';
    case Error   = 'danger';   // note: Bootstrap uses 'danger', some bundles use 'error'
    case Warning = 'warning';
    case Info    = 'info';
}

Nail down the string contract between PHP and JS early. A mismatch between error and danger produces a message that renders with no styling at all — silently, in production, and it looks like "the package is broken."

Pattern 4 — One helper for redirect-and-flash

Flash messages are almost always paired with a redirect. Encapsulate the pair:

protected function backWith(string $type, string $message): RedirectResponse
{
    return redirect()->back()->with('flash', compact('type', 'message'));
}

In Symfony-land the same idea is a trait or an abstract controller method calling $this->flash->{$type}() before the redirectToRoute.

Pattern 5 — AJAX / Inertia / Livewire boundary

If your frontend does partial reloads, the flash has to survive the boundary. Two viable approaches:

  • Server-driven: keep flash in the session, read it on the next full request, and let the JS renderer attach to [data-flash] nodes on DOMContentLoaded. Cheap, but doesn't work for XHR responses that never touch a layout.
  • Payload-driven: return the flash in the JSON envelope and call the renderer directly.
fetch(url, {headers: {'X-Requested-With': 'XMLHttpRequest'}})
  .then(r => r.json())
  .then(({flash}) => flash && window.FlashAlert.show(flash.type, flash.message));

The bundle's pure-JS renderer is the useful part here — it's framework-free, so this porting path is the least painful.

Pattern 6 — Testing the contract

Whatever you build, assert on the session payload, not on rendered HTML:

$this->post('/orders', $data)->assertSessionHas('flash.type', 'success');
// Symfony
$this->assertTrue($session->getFlashBag()->has('success'));

If you find yourself asserting on CSS classes, your test is coupled to the renderer — which is the piece most likely to change or need replacing.


Gotchas and Tips

It's Symfony-only, and there's no adapter. No FlashAlertServiceProvider, no Flash facade, no publishable config. If you composer require this into a Laravel app you'll get an autoloaded class or two that reference Symfony SessionInterface and AbstractBundle types. Depending on your Symfony components version in Laravel, some of it may load — which is worse than a hard failure, because it creates the illusion of a supported integration.

Zero stars, zero dependents, zero recent activity is the headline risk. For a package this small the risk isn't bugs, it's abandonment: it will pin to old Symfony versions and block your major upgrades. If you adopt it in Symfony, fork it or vendor the ~3 files you actually use. For a Laravel project this is a firm "don't — write the 40 lines yourself."

Flash semantics differ between the frameworks. Symfony's FlashBag is a bag of arrays keyed by type — getFlashBag()->add('success', '...') and multiple messages per type. Laravel's session()->flash() stores a single value per key unless you use ->push(). If you're porting, you need session()->push('flash', [...]) or a namespaced array, otherwise your second message on the same request silently overwrites the first.

Peek vs. get. Symfony's getFlashBag()->get('success') consumes the messages; peek() does not. A layout that renders flashes on both an error page and a base.html.twig extension of it will show them twice — or zero times. Laravel's session('flash') is non-consuming for the current request, so the analogue is "renders twice on the same request but vanishes on the next." Both are confusing; test the redirect()->back() path specifically, because that's the one users actually hit.

Escaping. The renderer is vanilla JS and may inject into innerHTML. Verify whether the bundle escapes message content. If it doesn't, and you're building messages from user input ("Invite sent to {$email}"), you have an XSS vector. In Laravel/Blade, {{ }} saves you by default — don't switch to {!! !!} to "fix" a broken message.

Asset pipeline is the real setup cost. Resources/public is not served from a web-accessible path in Symfony. You need assets:install (or a Webpack Encore alias), plus the file gets re-copied on every composer install. In Laravel terms this is the vendor:publish step — except there's nothing doing it for you automatically. Budget more time here than for the PHP side.

CSS framework mismatch. The generated markup will carry classes for whichever CSS the bundle was authored against (Bootstrap 3-era is common for packages like this). Under Tailwind or Bootstrap 5 those class names either do nothing or conflict. The fix is one template override — check whether the bundle supports template overriding via Resources/views in your app, and if not, copy the template into your own namespace and include that instead.

Ordering is not guaranteed. Symfony's FlashBag preserves insertion order per type, but a naive renderer that loops types in a fixed array order will group all successes before all errors regardless of when they occurred. If ordering matters (it usually doesn't), flatten to a single ordered list instead of a type-keyed map.

Translation. Messages are pre-rendered strings by the time they reach the renderer, so |trans has to happen at flash time, not display time. Flash a translation key instead if you have a multi-locale app — otherwise a user who switches language mid-session sees the old locale's message. (Low priority, but it's a one-way door: changing it later means touching every controller.)

Extension point to prefer. If you do adopt the bundle, the cleanest customization seam is a custom Twig template that keeps using the bundle's service and skips its markup entirely. That way the message vocabulary and the flash-bag handling stay consistent, and you're only replacing the ~15 lines of HTML/JS you disagree with. Avoid subclassing the service unless the bundle was designed for it — small packages rarely mark their internals final correctly, and you'll inherit the maintenance burden either way.

Verdict for a Laravel developer: read the repo for the pattern, skip the dependency. The genuinely reusable idea is "a tiny service wrapping session flash + one guarded layout partial + a framework-agnostic JS renderer you control." Everything else is framework glue you'd rewrite anyway — and rewriting 40 lines is cheaper than carrying an unmaintained Symfony dependency into a Laravel app.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console