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

Sweet Alert Laravel Package

realrashid/sweet-alert

Laravel package that brings SweetAlert2 to your app with a fluent PHP API. Flash success, error, and toast alerts, or build confirm dialogs right from your controllers—no JavaScript boilerplate needed.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish in one pass:

composer require realrashid/sweet-alert
php artisan vendor:publish --provider="RealRashid\SweetAlert\SweetAlertServiceProvider"

Publishing gives you config/sweetalert.php (CDN vs bundled assets, theme defaults, middleware behaviour) and the package JS/CSS. Then put the directive in your main layout, just before </body> so it renders after your own JavaScript:

    @sweetAlert
</body>

@sweetAlert is the v8 directive; on v7 and earlier the include is @include('sweetalert::alert'). Nothing renders without one of them — the fluent API only writes to the session, and the view is what turns that into JavaScript.

First use case — flash a result across a redirect. This is 90% of real usage: a controller action finishes, redirects, and the next page shows the message.

use RealRashid\SweetAlert\Facades\Alert;

public function store(StorePostRequest $request)
{
    $post = Post::create($request->validated());

    Alert::success('Post created', 'You can keep editing it below.')->flash();

    return redirect()->route('posts.edit', $post);
}

The ->flash() call is what makes it survive the redirect; omit it and the dialog fires on the current response instead. For low-stakes feedback use toast('Saved') with the same ->flash().

Where to look first: config/sweetalert.php for asset delivery and defaults, the Alert facade for the builder surface (v8 added @method annotations, so IDE completion works), and the VitePress docs at realrashid.github.io/sweet-alert — particularly guide/upgrade-guide if the project is on v7.

Requirements for v8 are PHP 8.3+ and Laravel 11, 12 or 13. For an app already rendering Blade views, day-to-day leverage is high: it removes hand-rolled session()->flash('status', ...) plus Alpine/vanilla JS toast markup from every controller. For an API-only or heavily Inertia-driven app it matters much less, beyond the Inertia middleware.

Implementation Patterns

Flash-then-redirect as the default. Treat the builder as a session payload, not a renderer. Chain ->flash() and return a redirect; the layout directive does the rest. This keeps controllers free of response()->json or view-local alert variables and survives the POST-redirect-GET cycle.

Toasts for non-blocking feedback, modals for decisions. toast() for "saved", "copied", "queued". Alert::success()/info()/warning()/error()/question() for anything the user must acknowledge. Set the default toast position once in config rather than per call — the v2 change removed the $position argument from toast() specifically to push that into config or ->position().

Guarded destructive actions with HTML attributes. This is the pattern worth standardising on across a codebase, because it needs no JavaScript on your side and no controller change:

<a href="{{ route('posts.destroy', $post) }}" data-confirm-delete>Delete</a>

<a href="{{ route('posts.publish', $post) }}" data-confirm data-confirm-method="PUT">Publish</a>

<form method="POST" action="{{ route('orders.refund', $order) }}" data-confirm>
    @csrf
    <button type="submit">Refund</button>
</form>

Override copy per element with data-confirm-title, -text, -icon, -button, -cancel. On confirm the package builds a form with the CSRF token and the correct method and submits it — so a data-confirm link never degrades into a bare GET against a destructive route. v8 fixed exactly that bug: in v7 the listener only existed on the request where confirmDelete() had been flashed, so on any other render the link was an ordinary link.

Input prompts that reach the server. Instead of intercepting the result in JS, point the prompt at a route:

Alert::input('What should we call you?')
    ->submitTo(route('profile.name'), 'POST', 'name')
    ->flash();

The answer is posted as a normal request, so you validate it with a normal FormRequest and keep the CSRF guarantees you already have.

Conditional chains. Every builder supports when() / unless() and macro(), which keeps controllers readable when a message varies by role or state:

Alert::success('Draft saved')
    ->when($request->user()->isAdmin(), fn ($alert) => $alert->footer('Visible to admins only'))
    ->flash();

Typed options. v8 ships AlertType, InputType and Position PHP 8.3 enums; prefer them over string literals so a typo is a static-analysis failure instead of a silently ignored option. macro() on the builders is the right extension point for house style — define a ->branded() macro once in a service provider rather than repeating footer/theme/button-styling calls in fifty controllers.

Split builders, not one god object. AlertBuilder, ToastBuilder and InputBuilder each carry their own defaults. Reach for the specific builder rather than trying to make one chain do everything; that's what the v8 rewrite was for.

Layered rendering. topLayer() puts a popup in the browser's top layer, above any z-index — the fix for toasts disappearing behind a fixed navbar. Use it for toasts and any alert triggered from inside a modal.

Vite/CDN choice is a config decision, not a per-page one. The package supports a CDN link, the bundled vendor/sweetalert/sweetalert.all.js, and config flags to always or never load the full bundle. Pick one strategy per project and record it in config, because mixing them is how you end up with two copies of SweetAlert2 fighting over window.Swal.

Gotchas and Tips

The html() signature trap is the reason the upgrade command exists. v7 was html($title, $code, $icon); v8 is html($html). PHP ignores surplus arguments, so an un-migrated call does not throw — it silently stops rendering. Run php artisan alert:upgrade --dry-run before touching anything; it tokenises your code rather than grepping, so ->html() on an unrelated object or the old binding name inside a comment gets reported instead of rewritten. Nothing is written without confirmation and vendor/ is never touched.

Check three config keys if the config was published under v7. background, width and padding are now null by default. SweetAlert2 applies each as an inline style that beats every stylesheet, so a leftover background value means no theme can ever change the popup colour. alert:upgrade fixes these too.

Nothing appears = the directive is missing or ordered wrong. The fluent API never throws when the view isn't wired up; it just writes session data nobody reads. First debugging step is always: view source, search for Swal, confirm the script tag and the inline fire call are present. Second step: check the session flash payload still exists on the request that renders — a double redirect or an Auth middleware bounce will consume or drop it.

Don't use it for API or JSON responses. Everything is session-flash and view-driven. In an AJAX/JSON flow the alert is written to a session the client never renders. For Inertia, use the middleware; for Livewire v4, use the trait.

Duplicate validation reporting. The middleware surfaces error messages as alerts automatically. If you also render a Blade error bag, users get two notifications for one failure. Toggle the middleware in config (v3.1.1 added the activate/deactivate switch) rather than suppressing one in the view.

Asset-loading surprises. v8 fetches SweetAlert2 on first click for guarded actions, so a page carrying only data-confirm links ships no JavaScript until someone uses it — good for payload, but it means the dialog depends on the CDN being reachable. The package falls back to the browser's native confirm() in that case, so a guarded delete is never submitted unasked. Verify this fallback survives your CSP before relying on it; a strict script-src will block the dynamic fetch and you'll get native confirms everywhere without an obvious error.

Prefer the attribute API over confirmDelete() in new code. confirmDelete() still displays immediately the way it always did, and existing calls keep working, but the always-present listener on data-confirm-delete is the more reliable behaviour — and it survives cache, fragment and non-flashed renders.

Test the session, not the DOM. Assert the redirect plus the flash payload in the session; asserting rendered SweetAlert markup turns a presentation change into a failing feature test. If you need the end-to-end check, do it once in a browser test rather than in every controller test.

Watch the config file across upgrades. This package has shipped config-key and signature changes in three separate majors. Treat config/sweetalert.php as code under review after any version bump, and re-run alert:upgrade --dry-run even when you think nothing changed — it's cheap and it catches the silent cases.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin