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

Fake Sms Notifier Laravel Package

symfony/fake-sms-notifier

Fake SMS integration for Symfony Notifier that routes outgoing SMS as email or log messages during development. Configure via DSN with fakesms+email or fakesms+logger to test notifications without sending real texts.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Verdict up front: this is a development-time test seam, not a capability. It earns adoption only if symfony/notifier is already (or is deliberately becoming) the SMS dispatch path. For a pure Laravel codebase it means introducing a second notification abstraction purely to fake one — a net architectural cost with no production payoff.

Architecture fit

  • The package is a Symfony Notifier bridge: it registers a TransportFactoryInterface for two DSN schemes — fakesms+email:// (renders the SMS body as an email through symfony/mailer) and fakesms+logger:// (writes to a PSR-3 logger). It is not an SMS SDK and holds no vendor logic.
  • Laravel's Notification / Channel stack is a parallel abstraction that does not consume Notifier transports. The two systems share a conceptual model (channel/transport + message) and nothing else.
  • Fit therefore splits cleanly: Symfony or mixed-stack services — native, zero adaptation. Laravel apps already pulling symfony/mailer — plausible, DSN swap only. Pure Laravel — requires a bridge channel we own and maintain forever.

Integration feasibility

  • Low effort in the right architecture. Configuration is a single env var, which matches Laravel's .env conventions:
    FAKE_SMS_DSN=fakesms+email://[email protected]&[email protected]
    
    The DSN host (default, mailchimp, …) selects a named mailer transport, which is the useful knob for per-team QA routing.
  • High effort in the wrong architecture. A Laravel channel adapter is ~40 lines (below), but it becomes load-bearing infrastructure that no upstream maintainer cares about.
  • The genuine value is code-path fidelity: production and non-production exercise the same NotifierInterface::send() call and the same message objects, with only the DSN differing. That is stronger than Notification::fake(), which bypasses dispatch entirely and can let a broken notification class ship.

Technical risk

  1. Dual-abstraction divergence. If Notifier is added only for dev, the production path is never exercised by it and vice versa. The seam proves nothing about the real transport.
  2. Version coupling. This is a subtree split of symfony/symfony; its version tracks Symfony's, not its own. v8.x requires PHP ≥ 8.4. On a Laravel 11/12 app (PHP 8.2) you must consciously pin to the 7.2–7.4 line or you will drag the whole symfony/* set up a major.
  3. Behavioural infidelity. The fake transport does not model 160-char GSM-7 segmentation, UCS-2 fallback, sender-ID registration, delivery receipts, throttling, or opt-out handling. Tests passing here say nothing about those.
  4. Thin usage signal. 27 stars, 0 dependents. Reassurance comes from "it ships inside Symfony," not from third-party validation — and the recent churn (v6.4.23 / v7.2.8 / v7.3.1 event-dispatcher fixes; v6.4.30 / v7.3.8 / v7.4.0-RC2 "do not use recipient phone numbers as sender e-mail addresses") confirms this is a lightly-exercised path.
  5. Eventing gap. The transports dispatch MessageEvent / SentMessageEvent / FailedMessageEvent on the contracts dispatcher; nothing forwards those into Laravel's event bus, so Laravel listeners will not observe fake SMS sends.

Key questions

  • Is symfony/notifier in the production dependency graph today? If no, this is a gate — do not proceed past a spike.
  • Which failure are we actually preventing: vendor SMS spend, rate-limit collisions, PII reaching a third party in non-prod, or flaky E2E assertions?
  • Is Notification::fake() plus Mailpit already sufficient for that failure? Usually it is.
  • Do we need segmentation/encoding/delivery-receipt fidelity? If so, this package does not help and a contract-test against the real provider sandbox does.
  • Who owns the adapter and the symfony/notifier version pin?
  • Does routing phone-number-bearing content into a shared QA inbox or log file satisfy our data-handling policy?

Integration Approach

Stack fit

  • Tier 1 — Symfony services / mixed monorepo: native. composer require --dev symfony/fake-sms-notifier and a DSN. Done.
  • Tier 2 — Laravel app already using symfony/mailer (e.g. via a shared package or a Symfony-based internal SDK): low friction; the email transport reuses the configured mailer, and Mailpit already captures the output.
  • Tier 3 — pure Laravel: poor fit without an adapter. Minimum viable bridge:
    final class FakeSmsChannel
    {
        public function __construct(private NotifierInterface $notifier) {}
    
        public function send(object $notifiable, Notification $notification): void
        {
            $message = $notification->toFakeSms($notifiable);
            $this->notifier->send(new SmsMessage($notifiable->routeNotificationFor('sms'), $message));
        }
    }
    
    Bind a Notifier built from FakeSmsTransportFactory in a service provider, register the channel, and gate it on app()->environment().

Migration path

  1. Phase 0 — decision spike (≤2 days). Prove the DSN resolves, one notification renders to email, and one renders to log. Exit criterion: a written go/no-go against the key questions above. Default answer should be no unless Tier 1 or Tier 2 applies.
  2. Phase 1 — environment wiring. Add FAKE_SMS_DSN to .env and .env.testing only. Never to .env.example as a default that could leak into a deploy.
  3. Phase 2 — dispatch path. Preferred: swap the DSN behind an existing Notifier transport. Fallback: the adapter above, owned by the team that owns notifications.
  4. Phase 3 — assertions. Assert on the observable artefact (mail in Mailpit, log line in a dedicated channel), not on internal Notifier state.
  5. Phase 4 — parity check. Route the same notification through the real provider's sandbox in one CI job to catch what the fake cannot.

Compatibility

  • Pin to the Symfony line that matches your PHP floor: Laravel 10 → symfony/* 6.4; Laravel 11/12 → 7.2–7.4. Treat ^8.0 as blocked until the app itself is on PHP 8.4.
  • Install as --dev; a fakesms DSN reaching production is a silent, total SMS outage.
  • Guard against duplicate MailerInterface bindings if symfony/mailer and Laravel's mailer coexist.
  • Use a dedicated log channel for fakesms+logger so fake SMS does not pollute stack/daily:
    'channels' => ['fakesms' => ['driver' => 'single', 'path' => storage_path('logs/fake_sms.log')]],
    
  • URL-encode to/from; + in the scheme is the transport-variant separator and must not be escaped.

Sequencing

  1. Spike and decision gate (Phase 0).
  2. composer require --dev symfony/fake-sms-notifier:<pinned-line> with an explicit symfony/notifier constraint.
  3. DSN in .env / .env.testing; dedicated log channel.
  4. Adapter (Tier 3 only) with unit test coverage.
  5. CI guardrails: fail the build if a non-prod env has a real SMS DSN, or if any prod env has a fakesms DSN.
  6. One parity job against the real provider sandbox.

Operational Impact

Maintenance

  • Issue tracking and PRs live upstream in symfony/symfony, not in this repo — there is no separate backlog to watch.
  • Release cadence rides the Symfony train. Most tagged releases are "no significant changes," which is low-churn but also low-signal: version bumps arrive whether or not you want them, so a pinned constraint and a Renovate/Dependabot rule scoped to the Symfony group are required.
  • Ongoing cost is dominated by the adapter (Tier 3), not the package. Budget it as owned code.

Support

  • No Laravel-facing documentation, negligible community surface; the effective onboarding material is Symfony's Notifier docs plus the DSN examples in the README.
  • Debuggability is genuinely good: email and log output are inspectable artefacts, no vendor console needed.
  • Onboarding is ~0.5 day for a Symfony-literate engineer, ~1–2 days for a Laravel-only engineer who also has to learn DSN semantics and the transport/notification split.
  • Requires a runbook entry: where fake SMS lands, how to switch DSNs, and how to tell a fake send from a real one.

Scaling

  • No production scaling surface — dev/test only.
  • The real scaling concern is CI noise: the email transport emits one message per recipient, so a bulk-notification test with thousands of recipients will hammer the mailer and the log channel. Mitigate with MAIL_MAILER=array, Mailpit as a sink, or a per-job DSN.
  • No throughput or concurrency characteristics worth designing around.

Failure modes

Scenario Impact Detection Mitigation
fakesms DSN present in production Total SMS outage, silent Env-diff check in deploy pipeline Hard fail in CI on fakesms:// in prod config
DSN typo / unknown mailer transport name Send throws or drops at runtime Smoke test on boot Assert transport resolves in a health check
Adapter owned by no one Breaks on Laravel/Symfony upgrade Post-upgrade test failures Named owner, unit tests on the channel
Phone-number PII in shared logs/inbox Data-handling finding Log review Dedicated log channel, retention policy, pseudonymised recipients
Symfony 8 drift raises PHP floor Composer resolution failure or runtime break CI install failure Pin symfony/* group, exclude 8.x until PHP 8.4
Green tests, real-provider failure False confidence shipped Production incident One sandbox parity job in CI
Email transport recursion (SMS-as-email triggers another SMS) Mail loop Mail volume anomaly Disable notifier on the receiving mailer transport

Ramp-up

  • Pros: single env var to learn; output is human-readable; no vendor account or API key needed for local dev; identical call path to production transports.
  • Cons: introduces a second notification abstraction most Laravel engineers have never used; the abstraction leak (Laravel listeners not firing, Laravel channels not understood) will surface as confusing bugs.
  • Recommended posture: time-box the spike, ship it only behind an existing Notifier path, install --dev with a pinned constraint, add the two CI guardrails (no fakesms in prod, no real SMS DSN in non-prod), and record an explicit "we chose Notification::fake() + Mailpit instead" decision if the gate fails — that negative decision is the most likely correct outcome for a Laravel-only stack.
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.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin