mgilet/notification-bundle
Symfony bundle that adds a flexible notification system to your app. Attach notifications to any entity via a trait and interface, create and manage them with a service, and display lists and unread counts through built-in controllers and Twig helpers.
Framework mismatch is still the headline risk, and 4.0 confirms it. The 4.0 release is unambiguously Symfony-native: the upgrade instructions require a YAML file at config/packages/mgilet_notification.yaml and removal of a Doctrine resolve_target_entities directive. Those are Symfony Flex recipe conventions and Doctrine bundle configuration — artifacts that have no meaning in a Laravel application. Nothing in 4.0 narrows the gap: no service provider, no facade, no config publish stub, no Eloquent mapping. The package remains non-installable in Laravel.
Architecture fit. Unchanged. The bundle's value is a domain model — a Notification entity attached to any "notifiable" entity via a join table, plus seen/unseen state and unseen-count helpers — tightly coupled to Doctrine entity mapping, Symfony DI compiler passes, and Twig rendering. 4.0 reinforces the coupling by making the notification class a first-class container configuration concern.
What 4.0 actually changes. This is a maintenance release, not a capability release. Two items:
NotificationManager::createNotification now returns the custom class rather than a base entity. Useful for anyone extending the model, but it arrives with a breaking configuration change (see Integration Approach).Technical risk. Still high and still concentrated in lifecycle, but the profile has shifted slightly:
Key questions for the team:
DatabaseNotification is strictly better.Stack fit.
| Target stack | Fit | Path |
|---|---|---|
| Laravel 10/11 | Poor | Do not integrate; port the schema, use native notifications |
| Symfony 3.4/4.4 (legacy) | Fair | Install as-is, but 4.0 targets 4.x+ conventions; verify before upgrading |
| Symfony 5+/6+ | Fair (improved slightly) | 4.0 modernization helps, but still fork before adoption; custom-entity config now possible natively |
| Framework-agnostic PHP | None | No PSR abstraction layer exists |
Recommended path (Laravel). Unchanged. Do not attempt a bridge; 4.0 makes the Symfony coupling more explicit rather than less. Treat the bundle as a specification for a schema:
notifications table (id, type, payload JSON, created_at) — matches Laravel's DatabaseNotification shape.notification_notifiable pivot with notifiable_type, notifiable_id, seen_at — the one genuinely useful idea: multi-entity attachment with per-entity read state.morphToMany on the notifiable side; a scoped unseen() query and a cached counter.Notification classes and channel manager.Migration path — 3.x to 4.0 (Symfony). 4.0 introduces a breaking configuration change for custom-entity users. Sequence it explicitly:
resolve_target_entities directive from the Doctrine configuration and add config/packages/mgilet_notification.yaml with mgilet_notification.notification_class: App\Entity\MyCustomNotification.NotificationManager::createNotification returns the custom class — this was previously broken, so any code branching on the returned type may now take a different path. Add a regression test that asserts the concrete class.Compatibility checks before any commitment.
composer.json vs. your runtime.phpstan at level 5+ against your target framework version. Budget 3–5 days for a Symfony 5 upgrade patch, more if Twig helpers are in play.Sequencing.
Maintenance. Assume full ownership from day one. The 4.0 release slightly improves the picture — a real fix, external contributors, an explicit upgrade guide — but does not change the posture. There is no formal release cadence, no LTS commitment, and no security-response process to file against. Pin the fork to a specific commit, vendor it under an internal namespace, and keep it on the quarterly dependency-review list explicitly. Budget ~1 day/quarter for compatibility patches, plus a one-time cost for the 4.0 config migration if a custom entity is in use.
Support. Documentation remains README/thin, though 4.0's upgrade section is a genuine improvement — it documents the exact YAML incantation and the directive to remove. Onboarding cost is low in absolute terms because the API surface is small, but it requires Symfony/Doctrine fluency a Laravel-native team will not have. If ported to Laravel, ramp-up drops to near zero.
Scaling. Unchanged from the prior assessment; the notification table is the growth vector.
(notifiable_type, notifiable_id, seen_at) — unseen-count queries are the hot path and will table-scan without it.Failure modes.
| Failure | Impact | Mitigation |
|---|---|---|
| PHP/framework upgrade breaks bundle | Blocks platform upgrade | Fork early; static analysis gate in CI |
| Doctrine major-version bump | Entity mapping breaks silently | Integration tests on mapping, not just services |
| Stored XSS via restored HTML rendering (4.0) | Account/session compromise in notification list | Sanitize on write or render; allowlist tags; CSP; security test fixtures |
| Partial 4.0 custom-entity migration | Silent fallback to base entity; wrong class returned | Assert concrete class in tests; verify config load in CI |
| Schema drift between environments | Notifications lost or double-counted | Migrations in version control, not bundle defaults |
| Unseen-counter N+1 | Latency spikes on dashboard load | Cache counters; assert query counts in tests |
| Unbounded table growth | Storage cost, slow queries | Scheduled pruning + archival |
| Low-adoption blind spot | No community CVE coverage | Internal security review on each fork update |
Bottom line. 4.0 is a competent maintenance release that fixes a real custom-entity bug and restores HTML rendering, and it demonstrates that the project is not fully abandoned. It does not change the strategic conclusion: the bundle is functionally superseded on Laravel and architecturally stale on modern Symfony. Its realistic value is as a reference design for multi-entity notification attachment with per-entity read state. Anyone adopting 4.0 on Symfony inherits one breaking config migration and one new security obligation — sanitizing rendered HTML — both of which must be handled before release, not after.
How can I help you explore Laravel packages today?