Comment créer un portail SMS avec Laravel et Twilio ?

March 22, 2019
Rédigé par
Brian Iyoha
Contributeur
Les opinions exprimées par les contributeurs de Twilio sont les leurs

xfZiGIwY7kMFumujtS99SsDUOzzE3HEluKNzI4Td5Ba7yorAqM9583sLeRzWPPuI2iDcAOjRAj2f0OZoGkCTjizc-ZoKWtWz98AHxpunO00UwgncR4v9XNn3bgJrLKPySdF2rbC0f2CuaGby8A

À un moment donné, dans le flux de travail de votre application, vous devrez peut-être transmettre des informations importantes à vos utilisateurs. À cette fin, grâce aux progrès des technologies Web, vous pouvez utiliser des notifications push. Cependant, la plupart de ces services exigent que vos utilisateurs disposent d'une connexion Internet et malheureusement, ce n'est pas toujours le cas. Heureusement, nous pouvons surmonter ce problème en utilisant un système de notification qui ne dépend pas d'Internet.

Dans ce tutoriel, vous découvrirez comment utiliser Programmable SMS de Twilio pour créer un portail de notification SMS à l'aide de Laravel. À la fin de ce tutoriel, vous aurez développé un portail de notification SMS personnalisé permettant d'avertir vos utilisateurs via un tableau de bord par SMS.

Prérequis 

Pour suivre ce tutoriel, vous avez besoin des éléments ci-dessous :

Configuration du projet

En premier lieu, nous devons créer un nouveau projet Laravel, soit avec le programme d'installation Laravel, soit avec Composer. Dans ce tutoriel, nous allons utiliser le programme d'installation Laravel. Si vous ne l'avez pas installé, consultez la documentation Laravel pour savoir comment procéder. Pour générer un nouveau projet Laravel, exécutez la commande suivante dans votre terminal :

$ laravel new sms-portal

Ensuite, remplacez votre répertoire de travail par sms-portal et installez le SDK Twilio via Composer :

$ cd sms-portal
$ composer require twilio/sdk 

Si Composer n'est pas installé sur votre PC, installez-le selon les instructions indiquées ici.

Après avoir installé le SDK PHP Twilio, nous devons obtenir nos identifiants Twilio à partir du tableau de bord Twilio. Rendez-vous sur votre tableau de bord et récupérez vos éléments account_sid et auth_token.

Capture d'écran des identifiants Twilio

Accédez maintenant à la section réservée au numéro de téléphone pour obtenir votre numéro de téléphone compatible avec les SMS.

Panneau de numéro actif dans Twilio

L'étape suivante consiste à mettre à jour le fichier .env avec nos identifiants Twilio. Ouvrez le fichier .env situé à la racine du répertoire du projet et ajoutez ces valeurs :

TWILIO_SID="INSERT YOUR TWILIO SID HERE"
TWILIO_AUTH_TOKEN="INSERT YOUR TWILIO TOKEN HERE"
TWILIO_NUMBER="INSERT YOUR TWILIO NUMBER IN [E.164] FORMAT"

Configuration d'une base de données

Maintenant que nous avons un projet de base de Laravel avec le SDK Twilio, créons notre base de données. Si vous utilisez une application GUI comme phpMyAdmin pour gérer votre base de données, créez une base de données nommée sms_portal et ignorez cette section. Si ce n'est pas le cas, si vous n'avez pas d'outil équivalent et si MySQL n'est pas installé, téléchargez MySQL depuis le site officiel pour votre plateforme.

Lancez le terminal et exécutez cette commande pour vous connecter à MySQL :

$ mysql -u {your_user_name}

REMARQUE : ajoutez l'indicateur -p si vous avez un mot de passe pour votreinstance MySQL.

Une fois la connexion établie, exécutez la commande suivante pour créer une nouvelle base de données :

mysql> create database sms_portal;
mysql> exit;

Ensuite, nous allons modifier la configuration de notre base de données en conséquence dans le fichier .env à la racine du dossier de ce projet.

DB_DATABASE=sms_portal
DB_USERNAME=root
DB_PASSWORD=

Création d'une migration

Maintenant que nous avons une base de données, nous allons créer une migration de base de données. Pour ce faire, il suffit d'exécuter cette commande dans notre terminal :

$ php artisan make:migration create_users_phone_number_table

Cela génère un fichier de migration {current_time_stamp}_create_users_phone_number_table dans le répertoire /database/migrations.

Maintenant, ouvrez le dossier du projet dans votre éditeur de texte/IDE favori pour commencer à apporter les modifications nécessaires. Ouvrez le fichier de migration que nous venons de créer. Le contenu doit être identique à celui-ci :

Création d'une migration dans l'IDE

Nous devons ajouter au tableau la colonne phone_number. Pour ce faire, modifiez la méthode up() comme suit :

public function up() {
    Schema::create('users_phone_number', function (Blueprint $table) {
        $table->increments('id');
        $table->string('phone_number'); 
        $table->timestamps();
    });
}

Notre fichier de migration est maintenant prêt à être migré. Pour effectuer la migration, il suffit d'exécuter la commande suivante dans le terminal :

$ php artisan migrate

La sortie doit ressembler à ce qui suit :

Sortie de la console avec artisan migrate

Création de l'interface utilisateur

À ce stade, nous avons configuré le projet. Il est temps de construire une interface utilisateur simple pour ajouter des données à notre base de données et pour envoyer des notifications SMS.

Ouvrez /resources/views/welcome.blade.php et apportez les modifications suivantes au bloc <head> :

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>SMS Portal With Twilio</title>
    <!-- Bootstrap styles CDN -->
     <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
</head>

Nous avons simplement supprimé le style initial de la page et ajouté Bootstrap à l'aide de BootstrapCDN pour simplifier le style. Nous allons ensuite créer deux formulaires sur la page. Un formulaire pour enregistrer le numéro de téléphone des utilisateurs, et l'autre pour envoyer des messages de notification personnalisés aux utilisateurs sélectionnés. Apportez les modifications suivantes au bloc body.

<body>
    <div class="container">
        <div class="jumbotron">
            <div class="row">
                <div class="col">
                    <div class="card">
                        <div class="card-header">
                            Add Phone Number
                        </div>
                        <div class="card-body">
                            <form>
                                <div class="form-group">
                                    <label>Enter Phone Number</label>
             <input type="tel" class="form-control" placeholder="Enter Phone Number">
                                </div>
                  <button type="submit" class="btn btn-primary">Register User</button>
                            </form>
                        </div>
                    </div>
                </div>
                <div class="col">
                    <div class="card">
                        <div class="card-header">
                            Send SMS message
                        </div>
                        <div class="card-body">
                            <form>
                                <div class="form-group">
                                    <label>Select users to notify</label>
                                    <select multiple class="form-control">
                                        @foreach ($users as $user)
                                        <option>{{$user->phone_number}}</option>
                                        @endforeach
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label>Notification Message</label>
                                 <textarea class="form-control" rows="3"></textarea>
                                </div>
             <button type="submit" class="btn btn-primary">Send Notification</button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

Si vous examinez de plus près le code ci-dessus, vous remarquerez que nous avons ceci :

      <select multiple class="form-control">
            @foreach ($users as $user)
              <option>{{$user->phone_number}}</option>
           @endforeach
      </select>

Ce fragment de code permet de générer un champ d'option pour chaque numéro de téléphone utilisateur disponible renvoyé avec cette vue. Nous mettrons en œuvre cette fonctionnalité par la suite.  

Stockage du numéro de téléphone des utilisateurs

Premièrement, créons un modèle exploitable pour interroger et insérer des enregistrements dans la base de données. Lancez le terminal dans le répertoire du projet et exécutez cette commande :

 $ php artisan make:model UsersPhoneNumber

Ouvrez le fichier créé dans app/UsersPhoneNumber.php et ajoutez le code ci-dessous :

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

class UsersPhoneNumber extends Model
{
   protected $table= "users_phone_number";
   protected $fillable = [
        'phone_number'
    ];
}

REMARQUE : voici quelques points à prendre en compte

  • L'ajout de protected $table= "users_phone_number"; indique à Eloquent le nom de la table à utiliser. Sans ce paramètre, le nom au pluriel de la classe sera utilisé comme nom de table. 
  • L'ajout de protected $fillable indique à Eloquent de rendre le champ attribuable en masse (pour en savoir plus, cliquez sur le lien ci-dessus).

L'étape suivante consiste à créer le contrôleur où nous allons mettre en œuvre la logique nécessaire pour le routage de chaque demande. Une fois de plus, lancez le terminal et exécutez la commande ci-dessous :

$ php artisan make:controller HomeController

Cela génère un fichier de contrôleur dans app/Http/Controllers/HomeController.php avec le contenu suivant :

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    //
}

Création de la méthode d'enregistrement de numéro de téléphone

Nous allons créer une fonction qui instancie un nouveau modèle UsersPhoneNumber avec les données transmises par le corps de la demande :

<?php

/**
 * Store a new user phone number.
 *
 * @param  Request  $request
 * @return Response
 */
public function storePhoneNumber(Request $request)
{
    //run validation on data sent in
    $validatedData = $request->validate([
        'phone_number' => 'required|unique:users_phone_number|numeric'
    ]);
    $user_phone_number_model = new UsersPhoneNumber($request->all());
    $user_phone_number_model->save();
    return back()->with(['success'=>"{$request->phone_number} registered"]);
}

Avec le code ci-dessus, nous exécutons une validation des données transmises par le corps $request avant de créer une nouvelle instance de UsersPhoneNumber. Après avoir enregistré le numéro de téléphone des utilisateurs, nous sommes redirigés vers la page d'accueil avec un message de réussite qui s'affiche rapidement (flash) dans la session.

Renvoi d'une vue avec les numéros de téléphone des utilisateurs

Nous devons maintenant renvoyer une vue avec les données des numéros de téléphone enregistrés. Nous allons écrire une fonction simple dans le HomeController qui interroge la table users_phone_number et renvoie les résultats de la demande dans la vue :

<?php

/**
 * Show the forms with users phone number details.
 *
 * @return Response
 */
public function show()
{
    $users = UsersPhoneNumber::all(); //query db with model
    return view('welcome', compact("users")); //return view with data
}

REMARQUE : compact() est une fonction PHP qui permet de créer un tableau avec des noms de variables et leurs valeurs.

Envoi de messages avec Programmable SMS de Twilio

Prochaine étape : mettre en œuvre l'envoi de SMS à l'aide de la bibliothèque Programmable SMS de Twilio. Créez une fonction privée dans le HomeController servant de fonction d'aide à l'envoi de messages :

<?php

/**
 * Sends sms to user using Twilio's programmable sms client
 * @param String $message Body of sms
 * @param Number $recipients string or array of phone number of recepient
 */
private function sendMessage($message, $recipients)
{
    $account_sid = getenv("TWILIO_SID");
    $auth_token = getenv("TWILIO_AUTH_TOKEN");
    $twilio_number = getenv("TWILIO_NUMBER");
    $client = new Client($account_sid, $auth_token);
    $client->messages->create($recipients, 
            ['from' => $twilio_number, 'body' => $message] );
}

La fonction reçoit deux paramètres : $message et $recipients. Nous récupérons ensuite nos identifiants Twilio stockés dans les variables d'environnement à l'aide de la fonction PHP getenv() intégrée, après quoi nous instancions un nouveau client Twilio avec les identifiants. Nous pouvons maintenant envoyer le SMS en appelant :

$client->messages->create($recipients, [
    'from' => $twilio_number, 
    'body' => $message
]);

La fonction Twilio messages->create() prend en compte deux paramètres d'un destinataire du message et d'un tableau avec les propriétés fromet bodyfrom est votre numéro de téléphone Twilio actif.

Envoi d'une notification utilisateur après l'enregistrement

À présent, nous avons terminé la fonction sendMessage() que nous utiliserons pour envoyer des messages aux utilisateurs. Nous allons mettre à jour la fonction storePhoneNumber() de sorte à avertir les utilisateurs une fois qu'ils ont été enregistrés avec succès. Pour ce faire, apportez les modifications suivantes à la fonction storePhoneNumber() :

<?php

/**
 * Store a new user phone number.
 *
 * @param  Request  $request
 * @return Response
 */
public function storePhoneNumber(Request $request)
{
    //run validation on data sent in
    $validatedData = $request->validate([
        'phone_number' => 'required|unique:users_phone_number|numeric',
    ]);
    $user_phone_number_model = new UsersPhoneNumber($request->all());
    $user_phone_number_model->save();
    $this->sendMessage('User registration successful!!', $request->phone_number);
    return back()->with(['success' => "{$request->phone_number} registered"]);
}

Super ! Maintenant, chaque fois que le numéro de téléphone d'un utilisateur est ajouté à notre base de données, nous pouvons envoyer à ce dernier un message de notification l'informant de l'action qui a été effectuée.

Envoi de notifications personnalisées

Ensuite, nous allons écrire une fonction permettant d'envoyer des messages personnalisés à certains utilisateurs. Ajoutez le code suivant à HomeController :

<?php 

/**
 * Send message to a selected users
 */
public function sendCustomMessage(Request $request)
{
    $validatedData = $request->validate([
        'users' => 'required|array',
        'body' => 'required',
    ]);
    $recipients = $validatedData["users"];
    // iterate over the array of recipients and send a twilio request for each
    foreach ($recipients as $recipient) {
        $this->sendMessage($validatedData["body"], $recipient);
    }
    return back()->with(['success' => "Messages on their way!"]);
}

Cette fonction transmet les données validées du corps $request à la variable $validatedData, ce qui nous permet d'itérer sur le tableau de $validatedData[users] et d'envoyer à chaque utilisateur le message reçu de $validatedData["body"]. Ensuite, nous redirigeons vers la page d'accueil avec un message qui s'affiche rapidement dans la session.

Création de routages

Nous avons créé les fonctions de contrôleur. Ajoutons maintenant des routages à l'application. Ouvrez routes/web.php et apportez les modifications suivantes :

<?php
Route::get('/', 'HomeController@show');
Route::post('/', 'HomeController@storePhoneNumber');
Route::post('/custom', 'HomeController@sendCustomMessage');

Mise à jour du champ de formulaire avec les routages

Ensuite, accédez à resources/views/welcome.blade.php et apportez les modifications suivantes au champ de formulaire :

//add the method attribute to the Register User form
// also add the name attributes to the input field 
<form method="POST">
    @csrf
    <div class="form-group">
        <label>Enter Phone Number</label>
        <input type="tel" class="form-control" name="phone_number" placeholder="Enter Phone Number">
    </div>
    <button type="submit" class="btn btn-primary">Register User</button>  
</form>

et

//add the method and action attributes to the Send custom message form
// also add the name attributes to the input fields 
<form method="POST" action="/custom">
    @csrf
    <div class="form-group">
        <label>Select users to notify</label>
        <select name="users[]" multiple class="form-control">
            @foreach ($users as $user)
            <option>{{$user->phone_number}}</option>
            @endforeach
        </select>
    </div>
    <div class="form-group">
        <label>Notification Message</label>
        <textarea name="body" class="form-control" rows="3"></textarea>
    </div>
    <button type="submit" class="btn btn-primary">Send Notification</button>
</form>

Test du code

Regroupons l'ensemble du code que nous avons créé jusqu'à présent. À ce stade, HomeController.php devrait ressembler à ceci :

<?php
namespace App\Http\Controllers;

use App\UsersPhoneNumber;
use Illuminate\Http\Request;
use Twilio\Rest\Client;

class HomeController extends Controller
{
    /**
     * Show the forms with users phone number details.
     *
     * @return Response
     */
    public function show()
    {
        $users = UsersPhoneNumber::all();
        return view('welcome', compact("users"));
    }
    /**
     * Store a new user phone number.
     *
     * @param  Request  $request
     * @return Response
     */
    public function storePhoneNumber(Request $request)
    {
        //run validation on data sent in
        $validatedData = $request->validate([
            'phone_number' => 'required|unique:users_phone_number|numeric',
        ]);
        $user_phone_number_model = new UsersPhoneNumber($request->all());
        $user_phone_number_model->save();
        $this->sendMessage('User registration successful!!', $request->phone_number);
        return back()->with(['success' => "{$request->phone_number} registered"]);
    }
    /**
     * Send message to a selected users
     */
    public function sendCustomMessage(Request $request)
    {
        $validatedData = $request->validate([
            'users' => 'required|array',
            'body' => 'required',
        ]);
        $recipients = $validatedData["users"];
        // iterate over the array of recipients and send a twilio request for each
        foreach ($recipients as $recipient) {
            $this->sendMessage($validatedData["body"], $recipient);
        }
        return back()->with(['success' => "Messages on their way!"]);
    }
    /**
     * Sends sms to user using Twilio's programmable sms client
     * @param String $message Body of sms
     * @param Number $recipients Number of recipient
     */
    private function sendMessage($message, $recipients)
    {
        $account_sid = getenv("TWILIO_SID");
        $auth_token = getenv("TWILIO_AUTH_TOKEN");
        $twilio_number = getenv("TWILIO_NUMBER");
        $client = new Client($account_sid, $auth_token);
        $client->messages->create($recipients, ['from' => $twilio_number, 'body' => $message]);
    }
}

et de notre côté, welcome.blade.php devrait ressembler à ceci :

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>SMS Portal With Twilio</title>
    <!-- Styles -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
        crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="jumbotron">
            @if (session('success'))
            <div class="alert alert-success">
                {{ session('success') }}
            </div>
            @endif
            @if ($errors->any())
            <div class="alert alert-danger">
                <ul>
                    @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
            @endif
            <div class="row">
                <div class="col">
                    <div class="card">
                        <div class="card-header">
                            Add Phone Number
                        </div>
                        <div class="card-body">
                            <form method="POST">
                                @csrf
                                <div class="form-group">
                                    <label>Enter Phone Number</label>
                                    <input type="tel" class="form-control" name="phone_number" placeholder="Enter Phone Number">
                                </div>
                                <button type="submit" class="btn btn-primary">Register User</button>
                            </form>
                        </div>
                    </div>
                </div>
                <div class="col">
                    <div class="card">
                        <div class="card-header">
                            Send SMS message
                        </div>
                        <div class="card-body">
                            <form method="POST" action="/custom">
                                @csrf
                                <div class="form-group">
                                    <label>Select users to notify</label>
                                    <select name="users[]" multiple class="form-control">
                                        @foreach ($users as $user)
                                        <option>{{$user->phone_number}}</option>
                                        @endforeach
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label>Notification Message</label>
                                    <textarea name="body" class="form-control" rows="3"></textarea>
                                </div>
                                <button type="submit" class="btn btn-primary">Send Notification</button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

Si votre code est identique, vous pouvez continuer. Si ce n'est pas le cas, vérifiez le code pour savoir ce qui manque.

Exécution de l'application

Ouvrez votre terminal, accédez au répertoire du projet et exécutez la commande suivante :

$ php artisan serve

Cela mettra en service votre application Laravel sur un port localhost, généralement le port 8000. Ouvrez le lien localhost qui s'imprime après avoir exécuté la commande dans votre navigateur. La page d'accueil devrait ressembler à ceci :

L'application Laravel s'exécute sur localhost

Enregistrez un nouveau numéro de téléphone. Si tout se passe bien, vous devriez recevoir sous peu un SMS vous informant de votre enregistrement.

Exemple de message texte du compte d'essai Twilio

 Vous pouvez aussi tester l'envoi de notifications personnalisées en sélectionnant un ou plusieurs utilisateurs dans le champ correspondant et en saisissant le texte à envoyer aux utilisateurs sélectionnés dans la zone de texte. Lorsque vous avez terminé, cliquez sur le bouton d'envoi de notification pour recevoir un SMS contenant le message de notification personnalisé.

Notifications personnalisées

Conclusion

Maintenant que vous avez terminé ce tutoriel, vous devriez être en mesure d'intégrer les SMS programmables Twilio dans votre application Laravel et d'envoyer des messages de notification par SMS. Si vous souhaitez consulter le code source complet de ce tutoriel, rendez-vous sur Github

Pour aller plus loin, permettez à vos utilisateurs d'effectuer des actions à partir des notifications qui leur sont envoyées par SMS. 

Je serais ravi de répondre à toutes vos questions concernant ce tutoriel. Vous pouvez me contacter via les canaux suivants :