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

Notification Laravel Package

trinity/notification

Trinity Notification is a Laravel package for building and managing in-app notifications. It offers database-backed storage, read/unread tracking, and customizable templates, with simple APIs for sending, listing, and marking notifications as read.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first. This package was last released 2017-12-07, has a single star and zero dependents. It is a module for the Modpreneur Trinity CMS (a Laravel-based admin/CMS), not a general-purpose Laravel notification library. Unless you are already running Trinity, there is no reason to install it — use Illuminate\Notifications instead. The steps below assume you have inherited a Trinity project that already depends on it.

  1. Confirm the actual package name and constraints before anything else:

    cat vendor/trinity/notification/composer.json
    

    The repo is modpreneur/trinity-notifications but the package is published as trinity/notification. Check the require block — you will almost certainly see laravel/framework: 5.4.*/5.5.* and a trinity/* core dependency. If your app is on Laravel 9+, stop here.

  2. Where to look first, in order:

    • composer.json — PHP/Laravel constraints and the Trinity core version it was built against.
    • src/Providers/*ServiceProvider.php — how it registers config, migrations, views, routes, and whether it uses defer.
    • config/ — the published config key (likely notification or notifications) and any model/table overrides.
    • database/migrations/ — the schema. This is the most useful file in the whole package; it tells you what a notification actually is here.
    • src/Models/ — the Notification model, its $fillable, casts, and any notifiable/user relation.
    • README.md — usually thin for packages of this vintage; do not trust it over the code.
  3. Install into an existing Trinity app (only if it is not already vendored):

    composer require trinity/notification
    
  4. Register the provider if there is no extra.laravel.providers entry (2017 packages often predate or skip package discovery):

    // config/app.php
    Trinity\Notification\NotificationServiceProvider::class,
    
  5. Publish and migrate:

    php artisan vendor:publish --provider="Trinity\Notification\NotificationServiceProvider"
    php artisan migrate
    

    Publish one tag at a time (--tag=config, --tag=migrations, --tag=views) so you can see exactly what landed and diff it against the vendor copy.

  6. First use case — notify a user and show an unread badge. From a controller or service:

    $notification = app(\Trinity\Notification\Notification::class);
    $notification->create([
        'user_id' => $user->id,
        'title'   => 'Order shipped',
        'body'    => "Order #{$order->id} is on its way.",
    ]);
    

    Then surface it: an unread count in your layout ($user->notifications()->unread()->count() — verify the actual scope names in the model) and an index page listing them, with a "mark as read" POST route.

Implementation Patterns

Treat it as a persistence layer, not a delivery layer. The value here is a notifications table plus an admin-facing UI. Wrap it so your application code never touches the package classes directly:

// app/Services/Notifier.php
class Notifier
{
    public function push(User $user, string $title, string $body, array $meta = [])
    {
        return Notification::create([
            'user_id' => $user->id,
            'title'   => $title,
            'body'    => $body,
            'data'    => $meta, // only if the schema has a json/text column
        ]);
    }
}

This single seam means a later migration to Illuminate\Notifications is a one-file change rather than a grep across the codebase — which, given the package's status, is the most likely outcome.

Traits on the User model. If the package ships a HasNotifications trait, add it to App\User and let it supply the notifications() relation. If the relation is defined in the package model instead, define your own relation on User pointing at the package model — do not scatter Notification::where('user_id', ...) through controllers.

Unread/read lifecycle. Model this explicitly. Typical pattern:

  • read_at nullable timestamp rather than a boolean — it is more useful and matches Laravel conventions.
  • A scopeUnread() and a markAsRead() method on your own repository class that wraps the package model.
  • Mark-as-read on the show action, not on the index — otherwise the badge disappears before the user reads anything.

Presentation. Publish the views and copy them into resources/views/vendor/notification/ (or whatever namespace the provider registers), then edit the copies. Never edit vendor/. Extract the list item into a partial so you can reuse it in both a full page and a dropdown.

Polling for the badge. Since this predates Laravel Echo usage in most Trinity apps, the pragmatic integration is a small JSON endpoint:

Route::get('/notifications/unread-count', fn () => [
    'count' => auth()->user()->notifications()->unread()->count(),
])->middleware('auth');

Hit it every 60s from a <script> in the layout. Cheap, boring, works.

Queued/evented fan-out. If you are generating notifications from domain events (order placed, ticket replied), do it in a queued listener, not in the controller. This package almost certainly has no queue integration of its own — queuing belongs to your application, and keeping DB writes off the request path is the main performance lever you have.

Admin integration. Trinity modules typically register an admin menu entry and CRUD screens. If the package does this, use it as-is for the "view all notifications / broadcast" screen and keep your user-facing UI separate. Two different audiences, two different views — merging them produces a screen nobody likes.

Gotchas and Tips

  • Name collision with Illuminate\Notifications. This is the biggest day-one trap. Illuminate\Notifications\Notification and Trinity\Notification\...\Notification are different classes with similar names, and IDE auto-import will pick the wrong one silently. Alias explicitly at the top of every file that touches both:

    use Trinity\Notification\Models\Notification as TrinityNotification;
    

    The same applies to config keys — a published config/notifications.php can shadow or be shadowed by Laravel's own notifications config depending on load order. Rename the published file to trinity-notification.php if you can, and update the provider's mergeConfigFrom/$configKey reference.

  • Laravel version assumptions. A 2017 package will use things that no longer exist or behave differently: str_slug(), array_get(), $defer on providers, Route::controller() (removed in 5.3+ style changes), and possibly the old Auth::user() facade without the Auth alias registered. If you are on Laravel 8+, expect to fork. The fork cost is usually 1–2 hours of mechanical fixes; budget for it rather than fighting composer install with --ignore-platform-reqs.

  • Migration conflicts. Duplicate or conflicting notifications table creation is common when both this package and a Laravel skeleton migration exist. Rename the package migration's timestamp/table or guard with Schema::hasTable() before create().

  • Publishing is all-or-nothing by default. vendor:publish --provider=... without a tag will overwrite config/app.php-adjacent files you may have edited. Always --tag=. Run php artisan vendor:publish --provider="..." --list (or check the provider source for publishes([...]) keys) to see the available tags.

  • Missing/undocumented scopes. Do not assume unread() exists — open the model and read the scopes. Packages of this era frequently have an is_read integer column and no scope at all. Write your own query scopes in a repository rather than relying on guesses from the README.

  • Mass assignment surprises. Check $fillable / $guarded on the model. If it is $guarded = [], a stray $request->all() in a controller can set user_id and spoof notifications to another user. Validate and whitelist explicitly at the boundary.

  • No community safety net. Zero dependents means zero Stack Overflow answers and zero forks to crib fixes from. Debugging approach: php artisan tinker the model directly, dd(app(...)->getRelations()), and Log::info() inside the provider's boot() to confirm registration actually happened — provider-not-registered is the cause of most "class not found" and "table doesn't exist" errors with packages this age.

  • Extension points worth using: config-driven model/table names (swap in a subclass of the package model), the view namespace (override templates without forking), and the service container (bind your own repository interface and resolve it everywhere). Avoid subclassing the package's controllers — route caching and admin-panel coupling make that brittle.

  • Have an exit plan. Because delivery, read state, and UI are all shallow concerns here, the migration path to native Illuminate\Notifications is: create a notifications table via php artisan notifications:table, add the Notifiable trait to User, and port each Notifier::push() call to a real Notification class. Do this the moment you touch more than two call sites — the package's 2017 constraints will cost you more than the rewrite.

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.
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
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource