Installation
Add the bundle to your composer.json:
composer require bassim/cm-sms-bundle
Enable it in config/bundles.php:
return [
// ...
Bassim\CmSmsBundle\BassimCmSmsBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console config:dump-reference Bassim\CmSmsBundle\Resources\config\services.yml > config/packages/cm_sms.yaml
Update config/packages/cm_sms.yaml with your CM Telecom credentials:
cm_sms:
username: 'your_username'
password: 'your_password'
sender_id: 'your_sender_id'
First Use Case Inject the SMS service into a controller or command:
use Bassim\CmSmsBundle\Service\SmsService;
class SendSmsController extends AbstractController
{
public function send(SmsService $smsService)
{
$response = $smsService->send(
'+212612345678', // Recipient
'Hello from Laravel!' // Message
);
return new Response($response);
}
}
Service Injection
Use dependency injection to access SmsService in controllers, commands, or services:
public function __construct(private SmsService $smsService) {}
Sending SMS Basic usage:
$smsService->send('+212612345678', 'Your message');
For bulk sends (if supported):
$smsService->sendBulk(['+212612345678', '+212698765432'], 'Broadcast message');
Error Handling Wrap calls in try-catch:
try {
$response = $smsService->send($phone, $message);
} catch (\Exception $e) {
// Log or handle CM Telecom API errors (e.g., invalid credentials, rate limits)
$this->addFlash('error', 'Failed to send SMS: ' . $e->getMessage());
}
Integration with Laravel Queues (Advanced) Dispatch a job for async sending:
use Bassim\CmSmsBundle\Jobs\SendSmsJob;
SendSmsJob::dispatch($phone, $message)->onQueue('sms');
(Note: Requires custom job class or queue listener setup.)
Logging Responses Log raw responses for debugging:
$response = $smsService->send($phone, $message);
\Log::debug('CM SMS Response', ['data' => $response]);
Configuration Overrides
Override config per environment (e.g., config/packages/cm_sms_test.yaml):
cm_sms:
username: '%env(CM_SMS_TEST_USERNAME)%'
sender_id: 'TEST_SENDER'
Testing Mock the service in PHPUnit:
$mock = $this->createMock(SmsService::class);
$mock->method('send')->willReturn(['status' => 'success']);
$this->container->set(SmsService::class, $mock);
Deprecated Symfony2 Bundle
ServiceProvider or DependencyInjection extensions.# config/services.yaml
Bassim\CmSmsBundle\Service\SmsService: ~
No Modern Laravel Support
// Example: Event listener for model events
class UserSmsListener
{
public function __construct(private SmsService $smsService) {}
public function handle(UserRegistered $event)
{
$this->smsService->send($event->user->phone, 'Welcome!');
}
}
Hardcoded Dependencies
SmsService class:
class CustomSmsService extends SmsService
{
protected function buildRequest($phone, $message)
{
// Override to adapt to new API
return [
'to' => $phone,
'text' => $message,
'new_param' => 'value',
];
}
}
config/services.yaml:
services:
Bassim\CmSmsBundle\Service\SmsService: '@custom_sms_service'
No Rate Limiting
class RateLimitedSmsService
{
public function __construct(private SmsService $smsService) {}
public function send($phone, $message)
{
if ($this->isRateLimited($phone)) {
throw new \RuntimeException('Rate limit exceeded');
}
return $this->smsService->send($phone, $message);
}
}
Security Risks
config/packages/cm_sms.yaml are exposed. Use environment variables:
cm_sms:
username: '%env(CM_SMS_USERNAME)%'
password: '%env(CM_SMS_PASSWORD)%'
Enable Verbose Logging
Add to config/packages/monolog.yaml:
handlers:
main:
type: stream
path: '%kernel.logs_dir%/%kernel.environment%.log'
level: debug
channels: ['!event']
Inspect Raw Requests
Decorate SmsService to log requests:
class DebugSmsService implements SmsServiceInterface
{
public function __construct(private SmsService $smsService) {}
public function send($phone, $message)
{
\Log::debug('SMS Request', [
'phone' => $phone,
'message' => $message,
'timestamp' => now()->toIso8601String(),
]);
return $this->smsService->send($phone, $message);
}
}
Test with CM Telecom’s Sandbox
Use a test sender ID (e.g., TEST123) and verify messages arrive in the CM Telecom sandbox environment.
Custom Response Handling Extend the bundle to parse CM Telecom’s API responses:
class CustomSmsService extends SmsService
{
protected function parseResponse($rawResponse)
{
if (isset($rawResponse['error'])) {
throw new \RuntimeException($rawResponse['error']['message']);
}
return $rawResponse['success'] ?? false;
}
}
Add Twilio/Vonage Fallback Implement a fallback service:
class MultiProviderSmsService
{
public function __construct(
private SmsService $cmSmsService,
private TwilioService $twilioService
) {}
public function send($phone, $message)
{
try {
return $this->cmSmsService->send($phone, $message);
} catch (\Exception $e) {
return $this->twilioService->send($phone, $message);
}
}
}
Laravel Notifications Channel Create a custom notification channel:
use Illuminate\Notifications\Notification;
class SendSmsViaCmTelecom implements ShouldQueue
{
public function via($notifiable)
{
return [new CmSmsChannel()];
}
public function toCmSms($notifiable, Notification $notification)
{
return $notification->toSms($notifiable);
}
}
How can I help you explore Laravel packages today?