symfony/clickatell-notifier
Symfony Notifier bridge for Clickatell SMS. Configure with a clickatell:// DSN using your access token and optional sender (from). Enables sending notifications via Clickatell through Symfony’s notifier transport system.
Notifier component, requiring a custom adapter layer to integrate with Laravel’s service container, event system, and HTTP client (Guzzle). The core Clickatell API logic (SMS delivery, retries) is transport-agnostic, but the Symfony-specific abstractions (e.g., TransportInterface, Message) necessitate a facade or decorator pattern for Laravel compatibility..env.Notifier support; requires manual implementation of Symfony’s Transport interface or a wrapper class.Messenger component (for async) is not directly usable; Laravel Queues would need to replicate its retry logic.CLICKATELL_DSN=clickatell://token@default?from=Sender).guzzlehttp/guzzle or symfony/http-client (for HTTP calls).symfony/options-resolver (for request validation), Laravel Queues (for async).| Risk Area | Severity | Mitigation Strategy |
|---|---|---|
| Symfony Abstraction Layer | High | Use a decorator pattern to wrap Symfony’s Transport in a Laravel-compatible interface. |
| Async Delivery Complexity | Medium | Implement Laravel Queues with exponential backoff (replicate Symfony Messenger’s retries). |
| API Versioning | Low | Abstract Clickatell API endpoints in a config file for future-proofing. |
| Error Handling | Low | Leverage Laravel’s Exception Handler and log errors to Sentry/Monolog. |
| Carrier-Specific Quirks | Medium | Test with Clickatell’s sandbox environment before production. |
retry_after delays).| Laravel Feature | Symfony Clickatell Notifier Fit | Workaround |
|---|---|---|
| Service Container | Medium (requires binding) | Register as a Laravel service provider. |
| HTTP Client (Guzzle) | High | Replace Symfony HTTP Client with Guzzle. |
| Queues | Medium (async support) | Use Laravel Queues with custom retry logic. |
| Events | Low | Dispatch Laravel events for lifecycle hooks. |
| Configuration (.env) | High | Use DSN format directly in .env. |
retry_after for failed jobs).Event system for Sent, Failed, Delivered hooks.Phase 1: Dependency Setup (1 day)
composer require guzzlehttp/guzzle symfony/options-resolver
.env configuration:
CLICKATELL_DSN=clickatell://ACCESS_TOKEN@default?from=SenderID
Phase 2: Adapter Layer (2–3 days)
// app/Services/ClickatellTransport.php
namespace App\Services;
use Symfony\Component\Notifier\Clickatell\ClickatellTransport as SymfonyClickatellTransport;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Illuminate\Support\Facades\Http;
class ClickatellTransport {
public function __construct(private string $dsn) {}
public function send(array $recipients, string $message) {
$client = Http::withOptions(['timeout' => 10]);
$symfonyTransport = new SymfonyClickatellTransport($this->dsn, $client);
return $symfonyTransport->send($recipients, $message);
}
}
AppServiceProvider:
$this->app->singleton(ClickatellTransport::class, function ($app) {
return new ClickatellTransport(config('services.clickatell.dsn'));
});
Phase 3: Async Integration (Optional, 1–2 days)
// app/Jobs/SendClickatellSms.php
namespace App\Jobs;
use App\Services\ClickatellTransport;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendClickatellSms implements ShouldQueue {
use Queueable;
public function __construct(
private array $recipients,
private string $message,
private ClickatellTransport $transport
) {}
public function handle() {
$this->transport->send($this->recipients, $this->message);
}
}
SendClickatellSms::dispatch($recipients, $message, app(ClickatellTransport::class));
Phase 4: Testing & Observability (1–2 days)
\Log::channel('clickatell')->info('SMS sent to ' . json_encode($recipients));
ClickatellTransport adapter.SmsSent, SmsFailed).How can I help you explore Laravel packages today?