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

Smssender Laravel Package

carpe-hora/smssender

A Laravel package that offers a simple, driver-based API for sending SMS messages through multiple providers. Configure your gateway, compose messages, and dispatch SMS from your application with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Check compatibility before installing. This package's last release was October 2014, so its composer.json will pin illuminate/support to a Laravel 4.x/early-5.x range. On a modern app the install is likely to fail outright:

composer require carpe-hora/smssender
# If it's blocked only by the illuminate constraint, either use a fork or:
composer require carpe-hora/smssender --ignore-platform-reqs

For a legacy L4/L5 app, add the service provider and facade alias to config/app.php by hand (there is no package auto-discovery from this era):

'providers' => [
    CarpeHora\SmsSender\SmsSenderServiceProvider::class,
],
'aliases' => [
    'Sms' => CarpeHora\SmsSender\Facades\Sms::class,
],

2. Publish and read the config first. The config file (config/sms.php after publishing) is the map of the whole package — it defines the default driver and each driver's credential keys:

php artisan vendor:publish --provider="CarpeHora\SmsSender\SmsSenderServiceProvider"

3. Where to look first, in order:

  • config/sms.php — which driver is default, and what keys each driver expects (from, key, secret, username, password, etc. — naming differs per provider).
  • src/ driver folder — confirms the exact send() signature and whether errors are returned or thrown.
  • README.md — the only documentation; it is thin, so the source is the real reference.

4. First use case — one transactional SMS. Put credentials in .env, reference them from the config (never call env() in application code), and send from a controller or command:

// config/sms.php
'default' => env('SMS_DRIVER', 'nexmo'),
'drivers' => [
    'nexmo' => [
        'from'    => env('SMS_FROM'),
        'key'     => env('NEXMO_KEY'),
        'secret'  => env('NEXMO_SECRET'),
    ],
],
Sms::send('Your order #1234 has shipped.', function ($sms) {
    $sms->to('+32470123456');
});

The closure-based "message builder" style is the package's core idiom: you hand it a body, then configure recipients (and optionally the sender) on the message object. Verify the exact method names against src/ before writing more than one call site.

Implementation Patterns

Wrap the facade behind your own interface. This is the single highest-leverage move, because it decouples the rest of the app from an unmaintained dependency and makes swapping providers (or replacing the package entirely) a one-file change:

interface SmsGateway {
    public function send(string $to, string $body): void;
}

class PackageSmsGateway implements SmsGateway {
    public function send(string $to, string $body): void {
        Sms::send($body, fn ($sms) => $sms->to($to));
    }
}

Bind it in a service provider and inject SmsGateway everywhere. Controllers, jobs, and listeners never touch Sms:: directly.

Per-message driver selection. For A/B rollouts or regional routing, use the driver-aware entry point rather than changing global config:

Sms::driver('twilio')->send($body, fn ($sms) => $sms->to($number));

Keep the default in config so normal traffic stays on the cheap provider, and reserve explicit driver() calls for exceptional cases.

Queue everything. Each send is an outbound HTTP call to a third-party gateway; doing it inline in a request adds hundreds of milliseconds and a failure mode to your user-facing path. Wrap it in a job:

class SendSms implements ShouldQueue {
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public string $to, public string $body) {}

    public function handle(SmsGateway $sms): void {
        $sms->send($this->to, $this->body);
    }

    public function retryUntil() { return now()->addMinutes(10); }
}

Give the job a bounded $tries and a backoff — SMS gateways are flaky and a naive retry loop will double-bill you.

Notification-style pattern. If the package predates Laravel's notification channels (it does), you can still get the ergonomics by writing a small SmsMessage value object and formatting in one place:

class SmsMessage {
    public function __construct(public string $to, public string $body) {}
    public static function make(...$args): self { /* normalize to E.164 here */ }
}

Centralizing normalization (E.164, sender ID, length) is where most SMS bugs live, so it belongs in your code, not scattered across call sites.

Multi-driver fallback. Because drivers are resolved through the container, you can loop over a priority list and degrade gracefully:

foreach (['nexmo', 'twilio'] as $driver) {
    try {
        Sms::driver($driver)->send($body, fn ($sms) => $sms->to($to));
        return;
    } catch (\Throwable $e) {
        report($e); // log, then try next
    }
}

Testing pattern. Never let the test suite hit a real gateway. Since the facade is backed by the container, either bind a fake gateway to your own interface or mock the facade:

Sms::shouldReceive('send')->once();
// or, cleaner, swap your binding:
$this->app->instance(SmsGateway::class, new FakeSmsGateway());

Gotchas and Tips

It's abandoned — budget for a fork, not a dependency. No release since 2014 and zero dependents on Packagist means no PHP 8+ compatibility, no void return types, and no security patches. Decide up front: fork it into packages/ and maintain it, or treat it purely as a reference implementation. Do not ship it on a modern Laravel without testing every driver you enable.

Phone number format is on you. Drivers expect E.164 (+32470123456). The package will not normalize, validate, or strip spaces. Store numbers normalized at the edge (registration, import) and assert format before sending.

Sender IDs and unicode differ per driver. Alphanumeric sender IDs (MYBRAND) are rejected by some gateways in some countries; non-GSM characters (emoji, accents) force UCS-2 encoding, which roughly halves the per-segment character budget and multiplies cost. If you send localized content, segment-length checks must be your own.

Errors may be returned, not thrown. Many 2014-era drivers return the gateway's response array (with an error code) rather than raising an exception. Inspect the return value — a silent failure looks identical to success. Wrap each call and assert on the response shape the specific driver documents.

env() in a cached config is dead. If you add env() calls outside config/sms.php and then run php artisan config:cache, they resolve to null. After changing credentials, run php artisan config:clear and confirm the driver actually received the value.

Old packages + service providers = manual registration. No auto-discovery, and the provider may register the facade/manager in a way that breaks under Laravel's later container refactors (e.g., typed Manager constructor changes). If Sms:: resolves to null or throws a binding error, the service provider is failing to boot — php artisan tinker and app('sms') will show you the real exception.

Delivery reports are not modeled. A successful send() means the gateway accepted the message, nothing more. If you need DLR/callback handling, that's a webhook endpoint you must build yourself and correlate with a stored message ID — the package won't give you one consistently across drivers.

Extension point: a custom driver. Adding a provider means implementing the package's driver contract and registering it in the config's drivers array. Read an existing driver in src/ first to copy the expected shape; the interface is small enough that a fork-and-add is realistic. But if the contract drags in old Illuminate classes, you'll spend more time shimming than writing — at which point a modern, maintained notification channel is the better call for greenfield work.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle