laravel-notification-channels/cmsms
A Laravel notification channel for CMS Made Simple (CMSMS). Send notifications from your Laravel app through CMSMS using the familiar Laravel notification API. Easy to install and configure, it extends the laravel-notification-channels ecosystem with a clean, tested driver for CMSMS-powered sites.
Architecture fit. The package is a transport adapter, not a subsystem: one channel class, one message value object, credentials read from config/services.php. It plugs into Laravel's existing fan-out (Notification::via()), which means queuing, retries, per-notifiable routing, and Notification::fake() all come from the framework rather than from this dependency. That is the right shape for a platform principle — every delivery destination is a notification channel — and it is worth adopting that principle regardless of whether this specific package survives. The package itself only makes sense if CMS Made Simple is already load-bearing in the estate and the intended recipients actually work inside the CMSMS admin. If a plain email or Slack message reaches those people, this dependency buys nothing.
Integration feasibility. Install is a single composer require with no publish step, which means config:cache behaves and there is no stale-config problem in CI. Configuration is config/services.php plus .env; on-demand routing (Notification::route('cmsms', $recipient)->notify(...)) and routeNotificationForCmsms() cover both ad-hoc and model-bound recipients. Realistically this is a days-scale spike, not an epic: install, map the payload, add a contract test, gate behind a flag.
The one unknown that gates the decision is the actual transport — authenticated HTTP POST, a CMSMS module route, or a direct database write. It is not stated in the README and must be read out of src/*Channel.php before anything else. A DB-write transport implies schema coupling and CMSMS DB credentials inside the Laravel app, which is a materially different security and upgrade-risk profile from an HTTP call. This single fact should drive adopt-vs-fork-vs-write-in-house.
Technical risk. The metadata is the risk statement: 9 stars, 0 dependents, single maintainer, MIT. Zero dependents means no one has validated this path in production — you will be the first to hit the bugs. Compounding that, the README's "Laravel 5 and up" framing is stale relative to the 2026-04-14 release date, so illuminate/* and PHP constraints must be checked manually against the target matrix. The package's small surface caps the downside: under MIT, forking into app/Support/Cmsms is an afternoon. Specific hazards to design around: notifications fail silently by default (a CMSMS 5xx with no queue means the message is simply gone); retries can double-post if the transport is not idempotent; a 200 response is not proof of delivery; credentials placed in config/cmsms.php would be baked into the cached config file; and notification bodies carry PII into a legacy CMS with its own retention and access model.
Key questions for the team.
composer.json constraints support Laravel 10/11/12 on PHP 8.2 without --ignore-platform-reqs?Stack fit. Conventional member of the laravel-notification-channels family: no service provider publishing, no migrations, no facade of its own. It composes with the existing queue, notification preferences, and test doubles. Treat it as a leaf: it should appear in exactly one notification class and one via() decision. Nothing in services, models, or controllers should use NotificationChannels\Cmsms\*, so a later fork or swap is a one-file change.
Migration path. There is no data to migrate — this is additive. The realistic migration is replacing ad-hoc curl/Guzzle glue or a bespoke service class with a notification class, which is also the point: the value is consolidating delivery behind one routing model and one testing story. Keep mail in the channel list as a fallback and gate CMSMS behind a feature flag plus a recipient guard, so flipping the flag off degrades to email rather than dropping messages:
$channels = ['mail'];
if (config('features.cmsms_notifications') && $notifiable->cmsms_recipient_id) {
$channels[] = 'cmsms';
}
Compatibility. Pin the exact version (:1.x.y, not ^1.0) and validate the constraint matrix by hand. If installation needs --ignore-platform-reqs, stop — that is a red flag, not a workaround. Confirm the string passed to via() against the service provider rather than trusting family convention, because a typo'd channel name fails silently.
Sequencing.
src/*Channel.php, then src/*Message.php, then the service provider — transport, real API surface, and channel name. Do not treat the README as complete.Http::fake() and asserts outbound payload shape and response handling. This is what converts a silent upstream break into a red CI build. Notification::fake() alone makes transport assertions vacuous.CmsmsNotifier::send(string $recipient, string $subject, string $body)) and bind it, so an in-house implementation is a binding change.Maintenance. Single maintainer, no downstream users, no release cadence guarantees. Budget explicit ownership: an engineer accountable for the pinned version, for reviewing upstream changes, and for executing the fork if the package goes dormant. The wrapper interface exists so that execution costs an afternoon rather than a project. Treat the Composer constraint as a tracked risk item, not a fire-and-forget line in composer.json.
Support. There is no SLA and no community backstop. This is a community dependency on a delivery path, and should be governed by whatever evidence bar the team applies to such things: pinned version, vendored-or-forkable source, wrapper, contract test, documented fallback. If the notification is contractual or compliance-relevant, decline and write the channel in-house — the code is small enough that this is a days-scale call, not a quarterly planning item. Good fit: internal operator alerts, editor pings, moderation nudges. Bad fit: customer-facing transactional messaging.
Scaling. A legacy PHP CMS behind an authenticated endpoint is not built for programmatic throughput. Queue on a dedicated, rate-limited worker (viaQueues() → 'cmsms' => 'cmsms') so a slow CMSMS cannot back up mail, database, or Slack delivery. Set $tries, $backoff, $timeout, and retryUntil() explicitly — Laravel's defaults are tuned for endpoints you control. Before enabling retries, confirm idempotency; otherwise a timeout-then-retry can double-post, so either include a dedupe key or cap retries at one.
Failure modes to instrument.
failed_jobs monitoring + alerting on channel error rate rather than reading logs after someone asks why they were never notified.via().config/cmsms.php cached to disk; use config/services.php + env() only.Ramp-up. Low. Any Laravel developer already knows notifications; the actual learning is three source files and one contract test. Expect a competent engineer to reach a safe, flagged, monitored internal notification inside a day, with the remaining effort in payload mapping and verification rather than in the package itself.
How can I help you explore Laravel packages today?