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

Twilio Bundle Laravel Package

simperfit/twilio-bundle

A Symfony bundle that integrates the Twilio PHP SDK, wiring Twilio client configuration and services into the container so applications can send SMS messages and make voice calls through Twilio with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Framework mismatch first. simperfit/twilio-bundle is a Symfony bundle, not a Laravel package. It does not ship a ServiceProvider, a facade, a publishable config file, or any php artisan integration. In a Laravel codebase your realistic options are:

  1. Use the official twilio/sdk directly (recommended — see below).
  2. Run a small Symfony service that uses the bundle and call it over HTTP from Laravel (only worth it if you already have Symfony infrastructure).
  3. Use a Laravel-native Twilio package instead of this one.

If you are working in an actual Symfony app (the only place this bundle fits):

composer require simperfit/twilio-bundle twilio/sdk

Register the bundle in config/bundles.php:

Vresh\TwilioBundle\VreshTwilioBundle::class => ['all' => true],

Configure credentials in config/packages/vresh_twilio.yaml:

vresh_twilio:
    sid: '%env(TWILIO_SID)%'
    token: '%env(TWILIO_TOKEN)%'

Add TWILIO_SID / TWILIO_TOKEN to .env, then inspect the container and see what you actually got registered:

bin/console debug:container | grep -i twilio
bin/console debug:container vresh_twilio

First use case — send an SMS. The bundle's job is to hand you a configured Twilio\Rest\Client wrapper. Inject the wrapper service and call through it (the wrapper typically proxies to the underlying client; run debug:container to confirm the exact accessor in the version you pulled):

use Vresh\TwilioBundle\Service\TwilioWrapper;

class Notifier
{
    public function __construct(private TwilioWrapper $twilio) {}

    public function sendSms(string $to, string $body): string
    {
        $message = $this->twilio->getTwilio()->messages->create($to, [
            'from' => '%env(TWILIO_FROM)%',
            'body' => $body,
        ]);

        return $message->sid;
    }
}

The Laravel equivalent you should actually write (no bundle involved):

composer require twilio/sdk
// app/Services/TwilioClient.php
namespace App\Services;

use Twilio\Rest\Client;

class TwilioClient
{
    private Client $client;

    public function __construct()
    {
        $this->client = new Client(
            config('services.twilio.sid'),
            config('services.twilio.token')
        );
    }

    public function sendSms(string $to, string $body): string
    {
        return $this->client->messages->create($to, [
            'from' => config('services.twilio.from'),
            'body' => $body,
        ])->sid;
    }
}

Bind it in AppServiceProvider::register() as a singleton and type-hint TwilioClient wherever needed. That is the whole feature set the bundle gives you, minus the Symfony ceremony.

Implementation Patterns

Constructor injection via a thin wrapper. Do not scatter new Client(...) calls through your code. In Symfony, inject TwilioWrapper; in Laravel, inject your TwilioClient singleton. Either way the rest of your code should never see sid/token.

Outbound messaging service. Wrap sending in a domain service with a stable signature (sendSms, sendWhatsApp, placeCall) so you can swap providers later. Return the Twilio sid and persist it — you will need it for status callbacks and support tickets.

class SmsService
{
    public function __construct(private TwilioClient $twilio) {}

    public function send(string $to, string $body, array $meta = []): string
    {
        $sid = $this->twilio->sendSms($to, $body);

        MessageLog::create([
            'sid'     => $sid,
            'to'      => $to,
            'payload' => $meta,
            'status'  => 'queued',
        ]);

        return $sid;
    }
}

Inbound webhooks and status callbacks. The bundle does not generate webhook routes for you — you still write the controller. For inbound SMS, Twilio POSTs form-encoded data; respond with TwiML:

Route::post('/twilio/sms', function (Request $request) {
    // $request->input('From'), ->input('Body'), ->input('MessageSid')

    return response(
        '<?xml version="1.0" encoding="UTF-8"?>'
        . '<Response><Message>Thanks!</Message></Response>',
        200
    )->header('Content-Type', 'text/xml');
});

If you use the Twilio SDK's TwiML builder, that is from twilio/sdk, not from this bundle — import it directly.

Status callback processing pattern. Expose a second endpoint for MessageStatusCallback, verify the X-Twilio-Signature header (Twilio SDK ships RequestValidator), then update your MessageLog row keyed by MessageSid. Make this idempotent — Twilio retries.

Testing pattern. Never hit the Twilio API in tests. Mock your own TwilioClient/wrapper in the container and assert on the arguments passed to sendSms. Because the bundle's service name is stable (vresh_twilio in Symfony, debug:container to confirm), you can swap it in services_test.yaml:

# config/packages/test/vresh_twilio.yaml
services:
    Vresh\TwilioBundle\Service\TwilioWrapper:
        class: App\Tests\Double\FakeTwilioWrapper

In Laravel, $this->mock(TwilioClient::class) in a feature test does the same job with less configuration.

Laravel integration tips if you insist on bridging from a Symfony service. Put Twilio behind an HTTP boundary: Laravel queues a job → job POSTs to your Symfony service's /sms endpoint → Symfony service uses the bundle. Do not try to load the Symfony bundle inside Laravel; the DependencyInjection, EventDispatcher, and Kernel contracts it depends on are not present.

Gotchas and Tips

You are not the target audience. This package is a Symfony bundle. In a Laravel app there is nothing to vendor:publish, no facade, no config/twilio.php. Any tutorial showing php artisan steps for this package is wrong.

Maintenance risk is severe. One star, zero dependents, and the last release was 2022-11-22. Treat it as effectively unmaintained:

  • It pins to a twilio/sdk major version circa 2022; if composer require twilio/sdk resolves a newer major, the bundle's constructor/signature assumptions may break.
  • Security fixes in the underlying SDK will not reach you through a version constraint you did not set yourself.
  • You are on the hook for reading the bundle source (it is small — one bundle class, one DI extension, one wrapper service) rather than expecting docs. vendor/simperfit/twilio-bundle/src/ is your documentation.

The bundle is a thin wrapper, not a client. It does not add retries, rate limiting, queueing, phone-number validation, or template management. Every production concern is yours:

  • E.164 formatting. Twilio rejects 555-1234. Normalize to +15551234567 before sending, and validate up front rather than eating a Twilio\Exceptions\RestException at 2 a.m.
  • Trial account limits. On a trial account you can only message verified numbers, and messages are prefixed with a trial notice. This looks like a bug and is not one.
  • Rate limits. Twilio returns HTTP 429 with a Retry-After header. Wrap sends in a queued job with ->backoff([10, 30, 60]); the bundle gives you no help here.
  • Long messages. Over 160 GSM-7 characters, Twilio splits the message and bills per segment. Encode-aware counting matters for non-GSM characters.

Credential and config quirks.

  • The config root is vresh_twilio (not twilio), so the obvious key name will silently fail validation. Run bin/console config:dump-reference vresh_twilio to see the real schema.
  • Symfony caches config aggressively: after editing the YAML or .env, bin/console cache:clear is mandatory. A stale container is the most common "it says the SID is null" cause.
  • Never commit credentials. Use %env(...)% and let Symfony's env var processors handle types; do not hard-code the auth token in the YAML.
  • The wrapper resolves credentials at container build, so changing .env in a running process requires a restart, not just a config reload.

Debugging checklist.

  1. bin/console debug:container vresh_twilio — confirm the service exists and inspect its class.
  2. bin/console debug:config vresh_twilio — confirm sid and token resolved to non-null values (they may be redacted; check length).
  3. Catch Twilio\Exceptions\TwilioException / RestException and log $e->getCode(), $e->getMessage(), and the Twilio status — the numeric code (e.g. 21211 invalid To) is far more useful than the message.
  4. Turn on the Twilio Console's Debugger for the account; it shows the raw request and Twilio's response for every failed call, which beats re-running your PHP.
  5. For webhook issues, check the Content-Type header (text/xml) and that the response body is valid TwiML — a 200 with HTML body will silently do nothing.

Signature validation is not optional for webhooks. Use Twilio\Security\RequestValidator from twilio/sdk with your auth token and the full request URL. Behind a proxy the URL Twilio signed differs from Laravel's $request->url() — use url()->current() carefully or reconstruct from X-Forwarded-*, or every callback rejects.

Extension points are limited. The bundle exposes essentially one service. Customization means either (a) decorating that service in services.yaml, or (b) skipping the bundle and instantiating Twilio\Rest\Client yourself, which in a Symfony app is a five-line service definition. For a Laravel developer, option (b) is the whole recommendation: you get the same client, a maintained SDK, and no Symfony bridge to maintain.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
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