flowcode/notificationbundle
A PHP notification bundle from flowcode that provides a structured way to create, manage, and deliver notifications within your application, with bundled components for quick setup and integration into existing projects.
First, accept the framework mismatch. This is a Symfony bundle, not a Laravel package. composer require flowcode/notificationbundle in a Laravel app will not load anything: there is no extra.laravel.providers, no service provider, and Laravel resolves Symfony components (symfony/mailer, symfony/console, etc.) via Composer — it does not boot Symfony bundles, which depend on Bundle subclasses, DependencyInjection/Extension, services.yaml tag-based wiring, and the Kernel lifecycle. With 0 stars and 0 dependents you also have no signal that anyone has ever tried it in a Laravel app.
So "getting started" for a Laravel developer is reconnaissance + reference extraction, not installation:
composer.json — PHP/Symfony constraints, PSR-4 root, and whether tagged releases exist. dev-main-only means no version you can pin safely.src/*Bundle.php and DependencyInjection/Configuration.php — Configuration.php is the real config tree; the README is likely stale. This is what tells you the shape of the abstraction: what channels exist, whether templates are first-class, how dispatch is queued.Resources/config/services.yaml — this defines the actual service IDs, the dispatcher, channel adapters, and any message bus tags. This is the "API surface" you would translate into Laravel bind/singleton calls if you fork.tests/ and LICENSE — if either is missing, stop. An unlicensed package is legally unusable commercially, and no tests means you verify everything yourself.First use case (if pursued at all): an internal-only, non-critical notification — admin alerts, deploy notifications, dev-environment logging — where a silent failure is annoying but not customer-visible or revenue-adjacent. Do not point this at transactional email, password resets, or billing alerts.
The pragmatic move on Laravel is to skip the bundle entirely and treat it as an architectural straw man. The shape worth copying is roughly:
interface Channel { public function send(Notification $n, Notifiable $to): void; }
class Notifier {
public function __construct(private array $channels) {}
public function send(Notification $n): void
{
foreach ($n->via() as $channel) {
$this->channels[$channel]->send($n, $n->recipient());
}
}
}
Laravel's native Notification + Notifiable + ShouldQueue already implements that shape with retries, failed_jobs, and NotificationFailed events built in. That's your first use case: use the native system, keep the bundle's design if it reveals a nicer channel contract.
Because there is no supported install path, every "pattern" below is really a choice between three options. Pick one explicitly and write it down.
Option A — Vendor-fork the class set (recommended if you use it at all).
Drop the *Bundle.php and DependencyInjection/ folder, keep the plain PHP classes under your App\Notifications\* namespace, and own them. Wire them in a ServiceProvider:
// app/Providers/NotificationServiceProvider.php
public function register(): void
{
$this->app->singleton(Notifier::class, function ($app) {
return new Notifier([
'mail' => new MailChannel($app['mailer']),
'inapp' => new InAppChannel(),
]);
});
}
You lose config-tree niceties, but you also lose the surprise of upstream changes breaking your container.
Option B — Bridge the bundle (only if you accept permanent coupling).
Write a ServiceProvider that manually instantiates the services declared in the bundle's services.yaml, skipping the Symfony DI extension. This is effectively option A with extra indirection; you re-read services.yaml on every upstream bump to check nothing drifted. In practice this is worse than A for a package with zero upstream cadence.
Option C — Reference only (default recommendation).
Read the package, write down the dispatcher interface and the config keys that interest you, then implement against Laravel's first-party Notification:
class OrderShipped extends Notification implements ShouldQueue
{
public function via($notifiable): array { return ['mail', 'database']; }
public function toMail($notifiable): MailMessage { /* ... */ }
public function toArray($notifiable): array { /* ... */ }
}
You get queue handling, ShouldQueue, database/broadcast/Slack channels, and retry semantics without touching a stranger's bundle.
Integration patterns that do transfer if you fork the code:
Channel object resolved from a map keyed by via().EventServiceProvider or dispatch a NotificationWasSent/NotificationFailed event for observability.config/notifications.php. Copy the config keys out of DependencyInjection/Configuration.php; do not try to parse Symfony YAML at runtime.implements ShouldQueue on the notification or by dispatching a job that calls your Notifier. Do not rely on an undocumented bundle queue driver.extra.laravel.providers means composer require installs files but boots nothing. If someone on the team reports "it's installed but nothing happens," that's why — it's not a bug in the package, it's the wrong distribution format.kernel.event_subscriber, custom tags collected by the bundle compiler pass) needs hand-rewriting as an explicit map or tap() in a provider.DependencyInjection/Configuration.php is the only reliable source for what keys exist and their defaults.LICENSE, you cannot ship this in a commercial product. This alone can kill adoption regardless of the code.NotificationFailed listeners, a fail-alert on the queue, and a dead-letter destination. An opaque bundle gives you none of that by default.composer update on a shared Symfony component is the first time anyone tests that combination. Pin aggressively if you vendor it.php artisan tinker and app()->make(YourNotifier::class) to inspect what got bound. If the binding resolves but nothing sends, the culprit is almost always a channel key mismatch between via() and your adapter map — trace from via() down, not from the entry point.How can I help you explore Laravel packages today?