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

Messages Laravel Package

orchestra/messages

A lightweight messaging component for Laravel that manages session-based notifications, alerts, and flash messages. Integrates smoothly with Orchestra Platform to provide consistent, reusable user feedback across your applications and admin panels.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and pin deliberately. This is a small Orchestra-family utility, not a framework — treat the version constraint as a decision, not a floating range:

composer require orchestra/messages:^6.1

^6.1 is the line that claims Octane support; earlier 6.0.x releases predate that fix. Before installing, open the package's composer.json and match its illuminate/* and PHP ranges against your app — that file is the only compatibility matrix you're getting.

Provider and config. Laravel auto-discovery should register Orchestra\Messages\MessagesServiceProvider. Publish whatever it ships and then inspect what landed rather than assuming:

php artisan vendor:publish --provider="Orchestra\Messages\MessagesServiceProvider"
# plus --tag=... if the provider declares tags; check the source

Where to look first, in this order:

  1. src/MessagesServiceProvider.php — this tells you whether the bag is bound as singleton, scoped, or bind. That single line is the whole Octane/queue-worker risk profile, and it tells you what facade alias (if any) is registered.
  2. The bag class itself (src/MessageBag.php or similar) — read the public methods end to end. The advertised API is four severities (success, error, warning, info) plus collection and rendering. The actual method names, whether they return $this for chaining, whether add() takes a key, and whether the flash key is configurable are all things to confirm from source, because vendor docs are thin.
  3. resources/views/ — if a Blade partial ships, read it before putting it in a layout. You need to know whether it escapes by default.
  4. Any config file — the four severity keys, message templates, and whether a driver/handler class is configurable, plus whether config is read at boot or per call (matters under config:cache).

First use case: the smallest end-to-end loop. Flash a message after a successful form submit, redirect, render the bag in your layout.

// app/Http/Controllers/PostController.php
public function store(StorePostRequest $request)
{
    $post = Post::create($request->validated());

    messages()->success('Post saved.');   // confirm exact helper/facade name in source

    return redirect()->route('posts.show', $post);
}
{{-- resources/views/layouts/app.blade.php --}}
@include('vendor.messages.partial')   {{-- or your own loop over the bag --}}

Do this on one page before anything else. It exercises the provider, the container binding, the session flash round-trip, and the Blade render — which is essentially the entire integration surface, in fifteen minutes.

Implementation Patterns

Put a seam in front of it on day one. This is the highest-leverage hour you'll spend. Do not let messages()->success(...) appear in fifty controllers.

// app/Support/Feedback.php
namespace App\Support;

use Orchestra\Messages\...;   // verify the concrete type from source

class Feedback
{
    public function success(string $message): void { /* delegate */ }
    public function error(string $message): void   { /* delegate */ }
    public function warning(string $message): void { /* delegate */ }
    public function info(string $message): void    { /* delegate */ }
}

Bind it in a service provider and type-hint Feedback in controllers. Call sites now depend on your interface. If the package stalls or you swap it out, you rewrite one class instead of grepping the codebase. That's what turns a third-party bet into a reversible implementation detail.

Render once, in the layout, via a wrapper component. Have exactly one place that renders messages, and put your design-system markup inside it so vendor Blade helpers never leak into feature views:

{{-- resources/views/components/feedback.blade.php --}}
@foreach (['success' => 'green', 'error' => 'red', 'warning' => 'amber', 'info' => 'blue'] as $level => $color)
    @foreach (feedback()->get($level) as $message)
        <div class="alert alert-{{ $color }}">{{ $message }}</div>
    @endforeach
@endforeach

Keep Laravel's $errors bag separate. They're different things with different lifecycles: $errors is validation feedback tied to a request and an input field; this is a general notice channel. Don't loop both into the same alert region — you'll get duplicated or interleaved output the first time a form both fails validation and flashes a message. Decide up front: validation renders at the field, messages render at the top.

Migrate module by module, not all at once. Pick one CRUD vertical, convert its ad-hoc session()->flash('status', ...) calls, run it for a sprint, then sweep. Delete the old pattern as each module converts — two coexisting conventions is worse than the one you started with.

Confirm multiple messages per severity actually append. If the bag is keyed rather than append-only, calling success() twice may overwrite. Look for an extend/add variant and test it explicitly — "we lost one of the two errors" is a production bug that a single-message smoke test won't catch.

Testing pattern: assert on the session, not on HTML.

$response = $this->post('/posts', [...]);
$response->assertSessionHas('messages');   // check the actual flash key from source

// Full round-trip render assertion:
$this->withSession([...])->get('/')->assertSee('Post saved.');

Under the array session driver flashes are dropped between test requests. That is the single most common reason "the message doesn't render in tests."

Console commands and queued jobs have no session. If your feedback service is injected into a job, it will either no-op silently or throw. Guard it, or give the abstraction a no-session mode (->forRequest() / a null driver) so the same call sites work in both contexts.

On API/Inertia/Livewire surfaces, only the collection half applies. There's no Blade partial to render. Either return the collected messages as part of a JSON envelope through your wrapper, or just own a hundred lines of internal bag. Don't let this package become the reason feedback UX is locked to server-rendered pages.

Gotchas and Tips

Octane and request-scoped state is the thing to verify yourself. A messaging layer is precisely where stale state shows up under persistent workers. If the bag is bound as a singleton and messages accumulate on the instance rather than flushing with the session, request two will render request one's messages. Read the provider binding; if it's a singleton, either wrap it with an explicit clear before/after each request, or re-bind with scoped() in your own provider. Then prove it: octane:start, hit the same page twice with a message in between. A changelog line saying "Added support for Laravel Octane" is a claim, not CI evidence — your smoke test is the evidence.

Queue workers have the same class of bug, worse. A long-lived worker that injects the bag into a job constructor will carry messages from job to job forever. Resolve inside handle(), not in the constructor.

Escaping is a security decision, not a styling preference. If any path lets a message contain markup — a DB-sourced string, an exception message, user-supplied content — then {!! !!} is stored XSS with a friendly face. Escape by default in your wrapper; if you genuinely need HTML in a notice, make it an explicit, reviewed, named method (->successHtml()) rather than the default. Check the vendor partial out of the box before trusting it.

Don't conflate this with notifications. The boundary is firm and worth writing into the team README: no email, SMS, push, database-persisted per-user notices, digests, retries, or rich templating. Anything that needs to survive the user closing their browser belongs in Laravel's notification system. If this package grows a "persist messages" feature request, the answer is no.

Debugging checklist when the partial renders nothing:

  • Is the provider actually loaded? php artisan about or app()->getLoadedProviders().
  • Is the view namespace right? view()->exists('vendor.messages.partial') in tinker.
  • Did you config:cache after publishing config? Config changes are invisible until you re-cache.
  • Is the flash key what you think? Inspect session()->all() after the redirect.
  • Is it a redirect at all? Messages set on a return view(...) response may never flash.

Zero stars and zero dependents is a real signal, but a bounded one. You're not adopting an ecosystem — you're adopting roughly a hundred lines of ergonomics wrapped around Laravel's own MessageBag. Weigh it accordingly. The fallback (a thin internal class with four methods) is cheap, so the correct posture is adopt cheaply, wrapper first, willing to swap. Every direct Blade reference to the package API is a line you rewrite later.

Verify the extension seam from source, not from the description. "Extensible drivers for custom delivery backends" is advertised but unspecified. If you plan to use custom message formats or handlers, read the contract class and how it's resolved from config before designing around it. Undocumented extension points are exactly the ones teams end up forking, which turns a dependency decision into a maintenance commitment.

Pin in composer.json and note the upgrade path. Since there's no published compatibility matrix beyond the package's own manifest and a sparse changelog, bumping the constraint should be a deliberate, tested change — particularly around any request-scope/Octane behavior, where regressions are invisible in a single-request functional test.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource