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

Backport Laravel Package

laravel-notification-channels/backport

Brings Laravel's modern notification channel features to older framework versions, letting legacy apps use mail, database, broadcast and other channels through a familiar, lightweight backport that requires minimal setup and keeps existing notification code unchanged.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm the framework version first. This package exists solely because Illuminate\Notifications\* does not ship with Laravel before 5.3. Run php artisan --version. On 5.3+ this dependency is dead weight — remove it and use the framework. On 5.1/5.2 you install it manually, because package auto-discovery does not exist in those versions:

composer require laravel-notification-channels/backport
// config/app.php
'providers' => [
    NotificationChannels\Backport\BackportServiceProvider::class,
],
'aliases' => [
    'Notification' => Illuminate\Support\Facades\Notification::class,
],

Read the source before the docs. There is no documentation site, the last release was November 2016, and there are zero dependents — the vendor directory is the specification. Open the package's composer.json and confirm the PSR-4 namespace it registers actually maps to Illuminate\Notifications\*. Every import you write depends on that mapping holding. If it differs, your code and your forward-portability change.

Publish and inspect the database stub. The database channel is inert until you publish and run the migration:

php artisan vendor:publish
php artisan migrate

Inspect the published schema before running it: you want uuid, notifiable_id, notifiable_type, type, data, read_at, and timestamps — the standard 5.3 notifications table. Divergence here tells you how much of the 5.3 API actually made it across.

First use case: mail, to yourself. Add the trait, write the smallest possible notification, and send it synchronously in tinker:

use Illuminate\Notifications\Notifiable;

class User extends Model
{
    use Notifiable;
}
namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class TestPing extends Notification
{
    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject('Backport check')
            ->line('If you are reading this, the shim works.');
    }
}
Notification::send(User::first(), new TestPing);
// or
User::first()->notify(new TestPing);

Mail is the right first proof because it exercises the widest surface at once: the Notifiable trait, the channel manager, the MailMessage builder, and whatever bridge translates a 5.3-style MailMessage into a 5.1-era Mail::send(). That last piece is the most likely to be incomplete — verify a real message lands in a real inbox (or Mailtrap) before trusting anything else. Once mail works end-to-end, everything after it is channel-by-channel verification, not new architecture.

Implementation Patterns

Write as if you are already on 5.3. This is the single highest-value discipline and it costs nothing. Import from Illuminate\Notifications\*, use via() / toMail() / toDatabase() / toArray() exactly as the 5.3 docs describe, use Notification::send() and $user->notify(), and use routeNotificationForMail() for recipient resolution. Never reach for a backport-specific class or a one-off workaround. If you keep this rule, the upgrade path is composer remove, one deleted provider line, one deleted alias line — and your notification classes survive untouched. The first shim-specific API someone invents becomes permanent debt.

Treat the Laravel 5.3 notification documentation as your reference manual. It is accurate for this package by design and it is the only real documentation you have.

Centralize dispatch behind an application-owned wrapper. Do not scatter Notification::send() through controllers and commands. One service gives you a swappable seam for logging, fallbacks, and feature flags:

class Notifier
{
    public function send($notifiable, Notification $notification)
    {
        try {
            Notification::send($notifiable, $notification);
        } catch (\Exception $e) {
            Log::error('notification.failed', [
                'type' => get_class($notification),
                'notifiable' => get_class($notifiable).':'.$notifiable->getKey(),
                'message' => $e->getMessage(),
            ]);
            throw $e;
        }
    }
}

This is also where a channel allow-list lives, so a broken provider SDK can be disabled without touching domain code.

Queue everything transactional. Adding ShouldQueue and SerializesModels is standard 5.3 practice and matters more here, because the 5.1/5.2 queue stack is older and the mail channel is the slow path:

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\SerializesModels;

class InvoicePaid extends Notification implements ShouldQueue
{
    use Queueable, SerializesModels;
}

Verify empirically, with a real driver (not sync), that via() is evaluated at dispatch time while the notifiable is serialized and re-resolved on the worker — and that a model deleted between dispatch and processing fails gracefully rather than fatally.

Model channel preferences inside via() instead of hardcoding. Since via() receives the notifiable, per-user preferences belong there. This is what lets you ship mail now and add database/in-app later without re-architecting:

public function via($notifiable)
{
    $channels = ['mail'];

    if ($notifiable->wants_in_app) {
        $channels[] = 'database';
    }

    return $channels;
}

Use custom channels instead of patching vendor code. When a built-in driver drifts against a modern SDK — Slack incoming-webhook payloads and Nexmo/Vonage are the likely casualties — register your own channel. A channel is just a class with send($notifiable, $notification), and it ports forward in a way a patched vendor file never will:

Notification::extend('slack_modern', function ($app) {
    return new ModernSlackChannel($app['config']['services.slack']);
});

Then via() returns 'slack_modern'.

Read the database channel through the trait, not raw queries. Notifiable gives you notifications(), unreadNotifications(), readNotifications(), markAsRead(), and unreadNotifications()->count(). Build the in-app list against those so query shape stays identical after the eventual upgrade. Keep toArray() payloads to IDs and short strings — the data column is JSON and becomes miserable to query and prune when fat.

Test every channel you actually ship. If Notification::fake() and assertSentTo() survived the backport, use them. If not, write a spy channel that records calls into an in-memory array and assert against it — roughly forty lines, and it catches every via() and serialization regression you will hit later. One test per production channel, no exceptions.

Gotchas and Tips

No auto-discovery, no facade alias, no migration — all manual. Class 'Notification' not found almost always means the missing alias line in config/app.php, not a broken package. Base table or view not found: notifications means the migration was never published. Both failures are configuration, not code.

MailMessage is the highest-risk component. The 5.3 builder assumes 5.3 mailables — markdown rendering, Mailable classes, Mail::to()->send() — none of which exist in 5.1/5.2. Whatever bridging the package does is the most likely thing to be partial. Test the full matrix early: plain line(), action() buttons, error(), attachments, and any markdown template. If markdown mail does not render, fall back to a custom mail channel calling Mail::send() with a Blade view — but keep toMail() returning a MailMessage-shaped object so domain code stays portable.

On-demand notifications almost certainly do not exist. Notification::route('mail', '[email protected]')->notify(...) was a 5.5 addition, not 5.3. Verify before designing the ops-alert path around it. The reliable alternative is a throwaway Notifiable model or an anonymous class implementing the trait with a routeNotificationForMail() override.

Composer resolution bites before feature code does. The package pins old illuminate/* constraints and an EOL PHP floor. Run composer why-not and composer update --dry-run against your exact PHP and Laravel minors before writing features. If your app pins illuminate/support tightly, you may need --ignore-platform-reqs or a root constraint edit — both red flags worth documenting for the next developer.

Vendor or fork on day one. Clone it, pin the commit, drop it into packages/ with a VCS repositories entry, assign a named owner, and commit the tests alongside it. There will be no upstream fixes and no community troubleshooting corpus. Budget hours to integrate and a day to harden, plus an ongoing stewardship line. You are the maintainer.

Watch for namespace collisions at upgrade time. When you move to 5.3+, the framework ships its own Illuminate\Notifications\*. Delete the provider and alias registrations before removing the package, then grep for stray use statements pointing at backport-only classes. If you followed the write-as-5.3 rule this is a clean deletion; if it isn't, someone quietly used a shim-specific API and that is your bug list.

File the exit ticket the day you adopt. A backport is a bridge, not an architecture. Pair adoption with an explicit "remove backport, upgrade framework" ticket and an owner, or it becomes a permanent commitment dressed up as a stopgap. The package's real day-to-day value is feature velocity now; the discipline of writing 5.3-shaped code is what keeps that velocity from calcifying into a second legacy layer.

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