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

Notify Laravel Package

gloudemans/notify

gloudemans/notify is a Laravel package that provides a simple notification system for your application. It offers a lightweight API for creating and managing notifications, making it easier to add user-facing messages and alerts without building the underlying infrastructure yourself.

View on GitHub
Deep Wiki
Context7

Getting Started

First, sanity-check the fit. gloudemans/notify (Crinsane/LaravelNotify) is a Laravel 5.0/5.1-era package (17 stars, 0 dependents, last meaningful activity ~2015). It predates Illuminate\Notifications, which shipped in Laravel 5.3 and covers the same ground with channels, queues, and mail. Adopt this only if you are maintaining a legacy app already on it, or you deliberately want its specific model: notifications stored as rows in two tables and rendered by polling, not pushed over a channel.

Install and wire it up:

composer require gloudemans/notify

Register the provider and facade in config/app.php:

Gloudemans\Notify\NotifyServiceProvider::class,
// aliases
'Notify' => Gloudemans\Notify\Facades\Notify::class,

Publish assets and run the migrations:

php artisan vendor:publish --provider="Gloudemans\Notify\NotifyServiceProvider"
php artisan migrate

Where to look first, in this order:

  1. composer.json of the package — check the illuminate/support constraint against your Laravel version. This is the single fastest way to know whether it will even boot.
  2. The published migrations — they create notifications (the catalogue of sent notifications) and user_notifications (per-user delivery + read_at pivot). Understanding these two tables is 80% of understanding the package.
  3. config/notify.php — model bindings, table names, view/route behaviour.
  4. The Notifiable trait and the Notify facade — the entire public API surface.

First use case: an in-app notification bell. Something happens (OrderShipped), you write one row via the facade, the user's header polls an endpoint returning unreadNotifications()->count(), and a dropdown renders the feed with a "mark as read" action.

Implementation Patterns

Attach the trait to your user model. This gives you the relations and unread scoping:

use Gloudemans\Notify\Traits\Notifiable;

class User extends Authenticatable
{
    use Notifiable;
}

If the trait name collides with another Notifiable, alias it on import (use Gloudemans\Notify\Traits\Notifiable as NotifyNotifiable;).

Send from a service, not a controller. Keep the facade call in one place so copy and types stay consistent:

Notify::send($user, 'Order shipped', 'Your order #1234 is on its way.', 'success');

Fan-out is the common case — pass a collection of users (an order's watchers, a team, an admin group) rather than looping in your controller.

Use notification "types" as your design contract. The package's type field (typically info, success, warning, danger) is what drives Bootstrap-style colouring in the default views. Define a small enum/constant list in your app and never pass raw strings from controllers — this is the cheap extension point that keeps the UI coherent as the product grows.

Build the read path explicitly. Three endpoints/partials cover the bell:

// count for the badge
auth()->user()->unreadNotifications()->count();

// feed
auth()->user()->notifications()->latest()->paginate(20);

// mark as read
$user->notifications()->whereKey($id)->first()->markAsRead();

Always route mark-as-read through a policy or ownership check — the pivot makes it trivial to mark someone else's notification read if you take the id straight from the request.

Poll, don't pretend it's realtime. A 30–60s setInterval fetch of an unread count is the intended pattern. If you need push, this package will not give it to you; layer a broadcast event on top and treat the DB rows as the durable record.

Prune on a schedule. Read notifications accumulate indefinitely. Add a scheduled command deleting user_notifications where read_at is older than N days, and orphaned notifications with no pivot rows. Without this, the badge query degrades on busy accounts within months.

Test against the tables. Use RefreshDatabase and assert assertDatabaseHas('user_notifications', ['user_id' => ..., 'read_at' => null]). Asserting on rows rather than on the facade's return value catches the fan-out and duplicate-delivery bugs that matter.

Gotchas and Tips

  • Trait name collision is the #1 trap. Laravel 5.3+ ships Illuminate\Notifications\Notifiable; this package ships its own Notifiable. You cannot use both unaliased in one model. Alias one, and be explicit in code review about which is which.
  • Table collision is #2. Laravel's built-in notifications use a single notifications table with a data JSON column. This package uses notifications plus user_notifications with different columns. If both exist in one app, the migrations will fight. Rename one set via the published config/migration.
  • It is abandoned. Expect breakage on modern Laravel: route auto-loading changed in 5.3+ and again at 8.x, service provider signatures tightened, and the $defer provider property was removed in Laravel 5.8. Budget for a fork rather than assuming composer require works.
  • Config cache. After editing config/app.php or config/notify.php, run php artisan config:cache clears — a stale cached provider list is a classic "facade class not found" red herring.
  • Eager-load the relations. Rendering a feed of 20 notifications with an actor/owner lookup per row is a textbook N+1. ->with(...) on the feed query.
  • Override views, don't edit them. Published Blade lives under resources/views/vendor/notify; anything you edit in place is lost on the next vendor:publish. Extend the package views and swap components instead.
  • No queueing, no channels, no digesting. Everything is synchronous and in-app. If the notification needs to be emailed or SMS'd, this package will not do it — write the mail separately and use the row purely as the in-app record.
  • Foreign keys are your friend. Add onDelete('cascade') to the user_id pivot if the package's migration doesn't; otherwise deleting a user silently corrupts unread counts and renders broken feed rows.
  • Duplicate sends on retry. The facade has no idempotency key. If you call it from a queued job that retries, guard with a uniqueness check on (user, type, reference) or wrap in DB::transaction with a dedupe row.
  • Verify signatures before you ship. The README is the only spec, and the exact send() argument order (recipient / title / message / type) is easy to invert silently. Write one integration test that asserts the stored row's columns at the very start of adoption — that test is your real documentation.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo