PHP code example of devwizardhq / laravel-textify

1. Go to this page and download the library: Download devwizardhq/laravel-textify library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

devwizardhq / laravel-textify example snippets


use DevWizard\Textify\Facades\Textify;

// Send a simple SMS
Textify::send('01712345678', 'Hello, this is a test message!');

// Send using specific driver
Textify::via('revesms')->send('01712345678', 'Hello from REVE SMS!');

// Chain methods for more control
Textify::to('01712345678')
    ->message('Your OTP is: 123456')
    ->via('mimsms')
    ->send();

// Send to multiple recipients
Textify::to(['01712345678', '01887654321'])
    ->message('Bulk SMS message')
    ->send();

// Create and send SMS notifications
$user->notify(new OrderShippedNotification('ORD-123'));

// Or send to any phone number
Notification::route('textify', '01712345678')
    ->notify(new WelcomeNotification());

public function via($notifiable): array
{
    return ['textify']; // or ['mail', 'textify'] for multiple channels
}

public function toTextify($notifiable): TextifyMessage
{
    return TextifyMessage::create('Your order has been shipped!');
}

public function routeNotificationForTextify($notification): ?string
{
    return $this->phone_number;
}



namespace App\Notifications;

use DevWizard\Textify\Notifications\TextifyMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;

class OrderShippedNotification extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public readonly string $orderNumber,
        public readonly string $trackingCode
    ) {}

    /**
     * Get the notification's delivery channels.
     */
    public function via($notifiable): array
    {
        return ['textify'];
    }

    /**
     * Get the SMS representation of the notification.
     */
    public function toTextify($notifiable): TextifyMessage
    {
        return TextifyMessage::create(
            message: "🚚 Order #{$this->orderNumber} shipped! Track: {$this->trackingCode}",
            from: 'MyStore',
            driver: 'revesms'
        );
    }

    /**
     * Get the array representation for logging/database
     */
    public function toArray($notifiable): array
    {
        return [
            'order_number' => $this->orderNumber,
            'tracking_code' => $this->trackingCode,
        ];
    }
}

class User extends Authenticatable
{
    use Notifiable;

    // Method 1: Route method (highest priority)
    // Gets notification context, most flexible
    public function routeNotificationForTextify($notification): ?string
    {
        // You can use notification context to determine logic
        if ($notification instanceof UrgentNotification) {
            return $this->emergency_phone ?? $this->phone_number;
        }

        return $this->phone_number;
    }

    // Method 2: Dynamic phone number method
    // Good for custom business logic
    public function getTextifyPhoneNumber(): ?string
    {
        return $this->preferred_sms_number ?? $this->phone_number ?? $this->mobile;
    }

    // Method 3: Automatic attribute detection (lowest priority)
    // Channel automatically checks these attributes:
    // phone_number, phone, mobile, phn, mobile_number, cell
}

// 1. TextifyMessage object (recommended for full control)
public function toTextify($notifiable): TextifyMessage
{
    return TextifyMessage::create(
        message: 'Your order has shipped!',
        from: 'MyStore',
        driver: 'revesms',
        metadata: ['order_id' => $this->orderId]
    );
}

// 2. Simple string (quick and easy)
public function toTextify($notifiable): string
{
    return "Order #{$this->orderNumber} has shipped!";
}

// 3. Array format (flexible structure)
public function toTextify($notifiable): array
{
    return [
        'message' => 'Your order has shipped!',
        'from' => 'MyStore',
        'driver' => 'revesms',
    ];
}

use App\Notifications\OrderShippedNotification;
use Illuminate\Support\Facades\Notification;

// Send to a single user
$user->notify(new OrderShippedNotification('ORD-123', 'TRK-456'));

// Send to multiple users
$users = User::where('wants_sms', true)->get();
Notification::send($users, new OrderShippedNotification('ORD-123', 'TRK-456'));

// Send to any phone number without a model
Notification::route('textify', '01712345678')
    ->notify(new WelcomeNotification());

// Queue the notification for background processing
$user->notify(
    (new OrderShippedNotification('ORD-123', 'TRK-456'))
        ->delay(now()->addMinutes(5))
);

public function toTextify($notifiable): TextifyMessage
{
    // Use different providers based on user preferences
    $provider = $notifiable->preferred_sms_provider ?? 'revesms';

    return TextifyMessage::create(
        message: 'Your notification',
        driver: $provider
    );
}

public function via($notifiable): array
{
    $channels = ['database']; // Always log to database

    // Add SMS for users who opted in
    if ($notifiable->sms_notifications_enabled) {
        $channels[] = 'textify';
    }

    return $channels;
}

use DevWizard\Textify\Events\TextifySent;
use DevWizard\Textify\Events\TextifyFailed;

Event::listen(TextifySent::class, function (TextifySent $event) {
    // Log successful SMS
    Log::info('SMS notification sent', [
        'recipient' => $event->message->getTo(),
        'message_id' => $event->response->getMessageId(),
    ]);
});

Event::listen(TextifyFailed::class, function (TextifyFailed $event) {
    // Handle SMS failures
    Log::error('SMS notification failed', [
        'recipient' => $event->message->getTo(),
        'error' => $event->response->getErrorMessage(),
    ]);
});

// Basic usage
Textify::via('dhorola')
    ->to('01712345678')
    ->message('Hello from DhorolaSMS!')
    ->send();

// Check balance
$balance = Textify::via('dhorola')->getBalance();

// Send SMS with custom sender ID
Textify::via('bulksmsbd')
    ->to('01712345678')
    ->from('CustomID')
    ->message('Hello from BulkSMSBD!')
    ->send();

// Check balance
$balance = Textify::via('bulksmsbd')->getBalance();

// Transactional SMS
Textify::via('mimsms')
    ->to('01712345678')
    ->message('Your OTP: 123456')
    ->send();

// The transaction type is configured in .env (T=Transactional, P=Promotional)

// Enterprise SMS with cost tracking
$response = Textify::via('esms')
    ->to('01712345678')
    ->message('Enterprise message')
    ->send();

// Access cost information
$cost = $response->getCost();

// Premium SMS service
Textify::via('revesms')
    ->to('01712345678')
    ->message('Premium SMS via REVE')
    ->send();

// Check account balance
$balance = Textify::via('revesms')->getBalance();
echo "Balance: $balance";

// Alpha SMS with SSL support
Textify::via('alphasms')
    ->to('01712345678')
    ->message('Hello from Alpha SMS!')
    ->send();

// Check balance
$balance = Textify::via('alphasms')->getBalance();

// Requires: composer )
    ->to('+1234567890')
    ->message('Hello from Twilio!')
    ->send();

// Requires: composer 
    ->to('+1234567890')
    ->message('Hello from Vonage!')
    ->send();

// Perfect for development - logs to Laravel logs
Textify::via('log')
    ->to('01712345678')
    ->message('This will be logged')
    ->send();

// Perfect for unit tests - stores in memory
Textify::via('array')
    ->to('01712345678')
    ->message('This will be stored in array')
    ->send();

// Access sent messages in tests
use DevWizard\Textify\Providers\ArrayProvider;
$messages = ArrayProvider::getMessages();

// Array format with different messages
Textify::send([
    ['to' => '01712345678', 'message' => 'Hello John!'],
    ['to' => '01887654321', 'message' => 'Hello Jane!'],
]);

// Same message to multiple numbers
Textify::send(['01712345678', '01887654321'], 'Same message for all');

// Single SMS
Textify::send('01712345678', 'Single SMS message');

// Send SMS in background
Textify::to('01712345678')
    ->message('Queued message')
    ->queue();

// Queue to specific queue
Textify::to('01712345678')
    ->message('Priority message')
    ->queue('high-priority');

use DevWizard\Textify\Events\TextifySent;
use DevWizard\Textify\Events\TextifyFailed;
use DevWizard\Textify\Events\TextifyJobFailed;
use Illuminate\Support\Facades\Event;

// Listen for SMS events
Event::listen(TextifySent::class, function (TextifySent $event) {
    logger('SMS sent successfully', [
        'to' => $event->message->getTo(),
        'provider' => $event->provider,
    ]);
});

Event::listen(TextifyFailed::class, function (TextifyFailed $event) {
    logger('SMS failed', [
        'to' => $event->message->getTo(),
        'error' => $event->exception?->getMessage() ?? $event->response->getErrorMessage(),
    ]);
});

// Listen for queued job failures
Event::listen(TextifyJobFailed::class, function (TextifyJobFailed $event) {
    logger('SMS job failed', [
        'to' => $event->getRecipient(),
        'provider' => $event->getProvider(),
        'error' => $event->getErrorMessage(),
        'metadata' => $event->getMetadata(),
    ]);

    // You could implement retry logic, alerting, etc.
});

// REVE SMS - Balance check
$balance = Textify::via('revesms')->getBalance();
echo "Balance: $balance";

// DhorolaSMS - Balance check
$balance = Textify::via('dhorola')->getBalance();

// BulkSMSBD - Simple balance check
$balance = Textify::via('bulksmsbd')->getBalance();

// Alpha SMS - Balance verification
$balance = Textify::via('alphasms')->getBalance();

// MimSMS - Account balance
$balance = Textify::via('mimsms')->getBalance();

// Single recipient
Textify::send('01712345678', 'Hello World!');

// Multiple recipients with same message
Textify::send(['01712345678', '01887654321'], 'Same message');

// Multiple recipients with different messages
Textify::send([
    ['to' => '01712345678', 'message' => 'Hello John!'],
    ['to' => '01887654321', 'message' => 'Hello Jane!'],
]);

Textify::via('revesms')->send('01712345678', 'Hello!');

Textify::driver('revesms')->send('01712345678', 'Hello!');

Textify::to('01712345678')->message('Hello!')->send();
Textify::to(['01712345678', '01887654321'])->message('Bulk SMS')->send();

Textify::to('01712345678')->message('Your OTP: 123456')->send();

Textify::via('bulksmsbd')
    ->to('01712345678')
    ->from('MyApp')
    ->message('Hello!')
    ->send();

$balance = Textify::via('revesms')->getBalance();
echo "Current balance: $balance";

// Send immediately via queue
Textify::to('01712345678')->message('Queued SMS')->queue();

// Send to specific queue
Textify::to('01712345678')
    ->message('Priority SMS')
    ->queue('high-priority');

$response = Textify::send('01712345678', 'Hello!');

// Check if SMS was sent successfully
if ($response->isSuccessful()) {
    echo "SMS sent! Message ID: " . $response->getMessageId();
} else {
    echo "Failed: " . $response->getErrorMessage();
}

// Available methods
$response->isSuccessful();        // bool - Check if SMS was sent successfully
$response->isFailed();            // bool - Check if SMS failed
$response->getMessageId();        // string|null - Get provider message ID
$response->getStatus();           // string - Get status message
$response->getCost();             // float|null - Get SMS cost (if supported)
$response->getErrorCode();        // string|null - Get error code
$response->getErrorMessage();     // string|null - Get error message
$response->getRawResponse();      // array - Get raw provider response

// Using via()
Textify::via('revesms')->send('01712345678', 'Hello!');

// Using driver() (alias)
Textify::driver('revesms')->send('01712345678', 'Hello!');

Textify::via('revesms')
    ->fallback('dhorola')
    ->send('01712345678', 'Message with fallback');

$providers = Textify::getProviders();
// Returns: ['dhorola', 'bulksmsbd', 'mimsms', 'esms', 'revesms', 'alphasms', ...]

if (Textify::hasProvider('revesms')) {
    // Provider is available
}

$provider = Textify::getProvider('revesms');
$balance = $provider->getBalance();

Textify::to('01712345678')->message('Test')->reset(); // Clears prepared data



namespace App\Notifications;

use DevWizard\Textify\Notifications\TextifyMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;

class OrderShippedNotification extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public readonly string $orderNumber,
        public readonly string $trackingCode
    ) {}

    /**
     * Get the notification's delivery channels.
     */
    public function via($notifiable): array
    {
        return ['textify']; // Add 'textify' to send SMS
    }

    /**
     * Get the SMS representation of the notification.
     */
    public function toTextify($notifiable): TextifyMessage
    {
        return TextifyMessage::create(
            message: "Your order #{$this->orderNumber} has been shipped! Tracking: {$this->trackingCode}",
            from: 'MyStore',
            driver: 'revesms' // Optional: specify SMS provider
        );
    }
}



namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    // Option 1: Route method (most specific, gets notification context)
    public function routeNotificationForTextify($notification): ?string
    {
        // You can use notification context to determine the phone number
        return $this->phone_number;
    }

    // Option 2: Dynamic getTextifyPhoneNumber method (custom logic)
    public function getTextifyPhoneNumber(): ?string
    {
        // Custom logic to determine phone number
        // Example: Use different numbers based on user preferences
        return $this->preferred_sms_number ?? $this->phone_number ?? $this->mobile;
    }

    // Option 3: Automatic attribute detection
    // If neither method above is defined, the channel will automatically
    // look for these attributes in this order:
    // phone_number, phone, phn, mobile, cell, mobile_number
}

class User extends Authenticatable
{
    use Notifiable;

    // Example 1: Use different numbers based on notification type
    public function textifyNumber(): ?string
    {
        // Use work phone during business hours, personal phone otherwise
        $now = now();
        if ($now->isWeekday() && $now->hour >= 9 && $now->hour <= 17) {
            return $this->work_phone ?? $this->phone_number;
        }
        return $this->personal_phone ?? $this->phone_number;
    }

    // Example 2: Format phone number dynamically
    public function textifyNumber(): ?string
    {
        $phone = $this->phone_number;

        // Ensure Bangladeshi format
        if ($phone && !str_starts_with($phone, '880')) {
            $phone = '880' . ltrim($phone, '0+');
        }

        return $phone;
    }

    // Example 3: Use notification preferences
    public function textifyNumber(): ?string
    {
        // Check if user has SMS notifications enabled
        if (!$this->sms_notifications_enabled) {
            return null; // Will prevent SMS from being sent
        }

        return $this->preferred_contact_number ?? $this->phone_number;
    }
}

use App\Notifications\OrderShippedNotification;

// Send to a single user
$user->notify(new OrderShippedNotification('ORD-123', 'TRK-456'));

// Send to multiple users
Notification::send($users, new OrderShippedNotification('ORD-123', 'TRK-456'));

// Queue the notification for background processing
$user->notify((new OrderShippedNotification('ORD-123', 'TRK-456'))->delay(now()->addMinutes(5)));

// 1. TextifyMessage object (recommended)
public function toTextify($notifiable): TextifyMessage
{
    return TextifyMessage::create(
        message: 'Your order has shipped!',
        from: 'MyStore',
        driver: 'revesms'
    );
}

// 2. Simple string
public function toTextify($notifiable): string
{
    return 'Your order has shipped!';
}

// 3. Array format
public function toTextify($notifiable): array
{
    return [
        'message' => 'Your order has shipped!',
        'from' => 'MyStore',
        'driver' => 'revesms',
    ];
}

use Illuminate\Support\Facades\Notification;

Notification::route('textify', '01712345678')
    ->notify(new OrderShippedNotification('ORD-123', 'TRK-456'));

use DevWizard\Textify\Events\TextifySent;
use DevWizard\Textify\Events\TextifyFailed;

Event::listen(TextifySent::class, function (TextifySent $event) {
    logger('Notification SMS sent', [
        'recipient' => $event->message->getTo(),
        'provider' => $event->provider,
    ]);
});

use DevWizard\Textify\Providers\BaseProvider;
use DevWizard\Textify\DTOs\TextifyMessage;
use DevWizard\Textify\DTOs\TextifyResponse;

class CustomSmsProvider extends BaseProvider
{
    protected array $supportedCountries = ['BD', 'US']; // Supported country codes

    public function getName(): string
    {
        return 'custom';
    }

    protected function getRequiredConfigKeys(): array
    {
        return ['api_key', 'sender_id'];
    }

    protected function validateConfig(): void
    {
        $this->ensureConfigKeys();
    }

    protected function getClientConfig(): array
    {
        return [
            'base_uri' => 'https://api.customsms.com',
            'timeout' => 30,
        ];
    }

    protected function sendRequest(TextifyMessage $message): array
    {
        $response = $this->client->post('/send', [
            'json' => [
                'api_key' => $this->config['api_key'],
                'to' => $message->getTo(),
                'from' => $message->getFrom() ?: $this->config['sender_id'],
                'message' => $message->getMessage(),
            ],
        ]);

        return json_decode($response->getBody()->getContents(), true);
    }

    protected function parseResponse(array $response): TextifyResponse
    {
        if ($response['status'] === 'success') {
            return TextifyResponse::success(
                messageId: $response['message_id'],
                status: 'sent',
                cost: $response['cost'] ?? null
            );
        }

        return TextifyResponse::failed(
            errorCode: $response['error_code'],
            errorMessage: $response['error_message']
        );
    }
}

'providers' => [
    'custom' => [
        'driver' => 'custom',
        'class' => App\Services\CustomSmsProvider::class,
        'api_key' => env('CUSTOM_SMS_API_KEY'),
        'sender_id' => env('CUSTOM_SMS_SENDER_ID'),
    ],
],

use DevWizard\Textify\Models\TextifyActivity;

// Activities are automatically tracked when enabled in config
$activities = TextifyActivity::latest()->get();

foreach ($activities as $activity) {
    echo "SMS to {$activity->to}: {$activity->status} at {$activity->created_at}";
}

// Filter by status
$failedSms = TextifyActivity::where('status', 'failed')->get();
$successfulSms = TextifyActivity::where('status', 'sent')->get();

// Filter by provider
$reveSms = TextifyActivity::where('provider', 'revesms')->get();

// Filter by date range
$todaySms = TextifyActivity::whereDate('created_at', today())->get();

use DevWizard\Textify\Events\{TextifySending, TextifySent, TextifyFailed, TextifyJobFailed};

// In your EventServiceProvider
protected $listen = [
    TextifySending::class => [
        SendingSmsListener::class,
    ],
    TextifySent::class => [
        SmsSuccessListener::class,
    ],
    TextifyFailed::class => [
        SmsFailureListener::class,
    ],
    TextifyJobFailed::class => [
        QueueJobFailureListener::class,
    ],
];

// Example listeners
class SmsSuccessListener
{
    public function handle(TextifySent $event)
    {
        // Log successful SMS
        logger('SMS sent successfully', [
            'to' => $event->message->getTo(),
            'provider' => $event->provider,
            'message_id' => $event->response->getMessageId(),
            'cost' => $event->response->getCost(),
        ]);

        // Update user notification status
        // Send webhook to external service
        // Update analytics dashboard
    }
}

class QueueJobFailureListener
{
    public function handle(TextifyJobFailed $event)
    {
        // Log job failure with detailed metadata
        logger('SMS queue job failed', $event->getMetadata());

        // Implement retry logic
        if ($this->shouldRetry($event)) {
            // Retry with different provider or after delay
            dispatch(new SendTextifyJob($event->getMessage(), 'fallback-provider'))
                ->delay(now()->addMinutes(5));
        }

        // Send alert to administrators
        // Update monitoring dashboard
    }
}
}

// config/textify.php
'fallback' => env('TEXTIFY_FALLBACK_PROVIDER', 'revesms'),

// Or in your .env file
TEXTIFY_FALLBACK_PROVIDER=revesms

// Multiple fallbacks can be configured by modifying the config file:
'providers' => [
    // Your primary providers...
],

// Custom fallback logic in your application
$primaryProviders = ['mimsms', 'revesms', 'alphasms'];
$fallbackProviders = ['dhorola', 'bulksmsbd', 'esms'];

foreach ($primaryProviders as $provider) {
    try {
        $response = Textify::via($provider)->send($phone, $message);
        if ($response->isSuccessful()) {
            break;
        }
    } catch (Exception $e) {
        // Try next provider
        continue;
    }
}
bash
php artisan vendor:publish --provider="DevWizard\Textify\TextifyServiceProvider" --tag="textify-config"
bash
php artisan textify:table
php artisan migrate