Skip to content

Instantly share code, notes, and snippets.

@shawnlindstrom
Last active October 19, 2024 05:55
Show Gist options
  • Save shawnlindstrom/42443d090e6d56a5a93c3ec90c46935b to your computer and use it in GitHub Desktop.
Save shawnlindstrom/42443d090e6d56a5a93c3ec90c46935b to your computer and use it in GitHub Desktop.
Twilio Service Provider for Laravel
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Twilio\Rest\Client;
class TwilioServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(Client::class, fn() =>
new Client(
$app->config['services.twilio.sid'],
$app->config['services.twilio.token']
)
);
}
}
@shawnlindstrom
Copy link
Author

Future me here. Abstract all your Twilio calls and inject the Client into those services or whatever you want to call them. Never put yourself in a situation where you have to mock the Client in order to test. It's not a flex if you can even pull it off. It's bad implementation. Code that is easy to test is objectively better than code that is hard to test or untestable.

<?php

namespace App\Services\Twilio;

use Twilio\Rest\Client;
use Twilio\Rest\Api\V2010\Account\CallInstance;

class Call
{
    public function __construct(private readonly Client $twilio) {}
    
    pubflic function create(string $to, $options = []): 
    {
        return $twilio->calls->create($to, config('services.twilio.from_number'), $options); 
    }
}

Use it in your controller as a real-time facade or just use DI (preferrably);

<?php

namespace App\Http\Controllers;

use Facades\App\Services\Twilio\Call;

class OutboundCallController extends Controller
{
     public function store()
     {
          $options = [
               // options like method, url, statusCallback, etc.
          ];
          Call::create('+17135551212', $options);     
     }
}

Then don't forget to test (oversimplified example):

<?php
 
namespace Tests\Feature\Http\Controllers;
 
use Facades\Twilio\Service\Call;
use Tests\TestCase;
 
class OutboundCallControllerTest extends TestCase
{
    public function test_a_call_can_be_created(): void
    {
        $to = '+16501231234';
        Call::shouldReceive('create')->once()->with($to); 

        $this->post(route('call.store'))
            ->assertOk();
    }
}

Personally, i don't use real-time facades. Mocking the service directly is almost as simple.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment