Erstellen eines SMS-Portals mit Laravel und Twilio

March 22, 2019
Autor:in:
Brian Iyoha
Mitwirkende:r
Die von Twilio-Mitwirkenden geäußerten Meinungen sind ihre eigenen

xfZiGIwY7kMFumujtS99SsDUOzzE3HEluKNzI4Td5Ba7yorAqM9583sLeRzWPPuI2iDcAOjRAj2f0OZoGkCTjizc-ZoKWtWz98AHxpunO00UwgncR4v9XNn3bgJrLKPySdF2rbC0f2CuaGby8A

An einem bestimmten Punkt in Ihrem Anwendungsworkflow müssen Sie möglicherweise wichtige Informationen an Ihre Nutzer:innen weitergeben. Dank des Fortschritts bei Webtechnologien ist dies mit Push-Benachrichtigungen ganz einfach möglich. Für die meisten dieser Dienste ist jedoch eine Internetverbindung erforderlich. Das ist leider nicht immer der Fall. Mit einem Benachrichtigungssystem, das nicht auf das Internet angewiesen ist, können Sie dieses Problem zum Glück lösen.

In diesem Tutorial zeigen wir Ihnen, wie Sie mit Programmable SMS von Twilio ein SMS-Benachrichtigungsportal mit Laravel erstellen. Damit können Sie Ihre Nutzer:innen dann über ein Dashboard per SMS benachrichtigen.

Voraussetzungen 

Für dieses Tutorial benötigen Sie Folgendes:

Projekt einrichten

Zunächst müssen Sie ein neues Laravel-Projekt erstellen, entweder mit dem Laravel-Installationsprogramm oder mit Composer. In diesem Tutorial werden wir das Laravel-Installationsprogramm verwenden. Wenn Sie es noch nicht installiert haben, finden Sie in der Dokumentation von Laravel eine Anleitung. Um ein neues Laravel-Projekt zu erstellen, führen Sie diesen Befehl in Ihrem Terminal aus:

$ laravel new sms-portal

Nun ändern Sie Ihr Arbeitsverzeichnis zu sms-portal und installieren das Twilio-SDK über Composer:

$ cd sms-portal
$ composer require twilio/sdk 

Sofern erforderlich, können Sie Composer gemäß den Anweisungen hier installieren.

Nach der Installation des Twilio PHP-SDK müssen Sie Ihre Twilio-Anmeldeinformationen aus dem Twilio-Dashboard abrufen. Gehen Sie zum Dashboard und kopieren Sie dort Ihre account_sid und das auth_token.

Screenshot mit Twilio-Anmeldeinformationen

Navigieren Sie jetzt zum Bereich Phone Number (Telefonnummer), um Ihre SMS-fähige Telefonnummer zu erhalten.

Bereich „Active Numbers“ (Aktive Nummern) in Twilio

Anschließend müssen Sie die Datei .env mit Ihren Twilio-Anmeldeinformationen aktualisieren. Öffnen Sie also die Datei .env, die sich im Stammverzeichnis des Projekts befindet, und fügen Sie diese Werte hinzu:

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"

Datenbank einrichten

Sie haben jetzt ein einfaches Laravel-Projekt mit installiertem Twilio-SDK. Erstellen Sie als Nächstes die Datenbank. Wenn Sie eine grafische Benutzeroberfläche (GUI) wie phpMyAdmin zum Verwalten Ihrer Datenbank verwenden, können Sie direkt mit der Erstellung einer Datenbank namens sms_portal fortfahren und diesen Abschnitt überspringen. Wenn Sie kein solches Tool haben und MySQL nicht installiert ist, installieren Sie MySQL von der offiziellen Website für Ihr Betriebssystem.

Öffnen Sie das Terminal und führen Sie diesen Befehl aus, um sich bei MySQL anzumelden:

$ mysql -u {your_user_name}

HINWEIS: Fügen Sie das Flag -p hinzu, wenn Sie ein Kennwort für Ihre MySQL-Instanz haben.

Nachdem Sie sich angemeldet haben, führen Sie den folgenden Befehl aus, um eine neue Datenbank zu erstellen:

mysql> create database sms_portal;
mysql> exit;

Ändern Sie nun die Datenbankkonfiguration entsprechend in der Datei .env im Stammverzeichnis Ihres Projekts.

DB_DATABASE=sms_portal
DB_USERNAME=root
DB_PASSWORD=

Migration erstellen

Nachdem Sie die Datenbank erstellt haben, können Sie die Datenbankmigration erstellen. Dazu müssen Sie einfach diesen Befehl im Terminal ausführen:

$ php artisan make:migration create_users_phone_number_table

Dadurch wird eine Migrationsdatei {current_time_stamp}_create_users_phone_number_table im Verzeichnis /database/migrations generiert.

Öffnen Sie nun den Projektordner in Ihrer bevorzugten IDE oder Ihrem Texteditor, damit Sie die gewünschten Änderungen vornehmen können. Öffnen Sie die eben erstellte Migrationsdatei. Der Inhalt sollte in etwa so aussehen:

Erstellen einer Migration in einer IDE

Sie müssen die Spalte phone_number zur Tabelle hinzufügen. Dazu können Sie die Methode up() wie folgt bearbeiten:

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

Die Migrationsdatei kann jetzt migriert werden. Führen Sie dafür folgenden Befehl im Terminal aus:

$ php artisan migrate

Die Ausgabe sollte in etwa so aussehen:

Konsolenausgabe von artisan migrate

Benutzeroberfläche erstellen

Das Projekt ist jetzt eingerichtet. Der nächste Schritt ist die Entwicklung einer einfachen Benutzeroberfläche, mit der Sie Daten zu Ihrer Datenbank hinzufügen und SMS-Benachrichtigungen senden können.

Öffnen Sie /resources/views/welcome.blade.php und nehmen Sie die folgenden Änderungen am Abschnitt <head> vor.

<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>

Sie haben jetzt den ursprünglichen Stil der Seite entfernt und Bootstrap mit BootstrapCDN hinzugefügt, um das Design zu vereinfachen. Als Nächstes erstellen Sie zwei Formulare auf der Seite. Eines für die Registrierung der Telefonnummer der Nutzer:innen und ein weiteres zum Senden nutzerdefinierter Benachrichtigungen an ausgewählte Personen. Nehmen Sie folgende Änderungen am Abschnitt body vor.

<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>

Wenn Sie sich den obigen Code genauer ansehen, werden Sie Folgendes feststellen:

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

Mit diesem Ausschnitt können Sie ein Optionsfeld für jede verfügbare Telefonnummer generieren, die in dieser Ansicht zurückgegeben wird. Sie werden diese Funktion in Kürze hinzufügen.  

Telefonnummer von Nutzer:innen speichern

Zunächst erstellen Sie ein Modell, das Sie zur Abfrage und zum Einfügen von Datensätzen in die Datenbank verwenden werden. Öffnen Sie Ihr Terminal im Projektverzeichnis und führen Sie Folgendes aus:

 $ php artisan make:model UsersPhoneNumber

Öffnen Sie die erstellte Datei unter app/UsersPhoneNumber.php und fügen Sie den folgenden Code hinzu:

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

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

HINWEIS: Beachten Sie folgende Punkte:

  • Durch Hinzufügen von protected $table= "users_phone_number"; wird Eloquent der zu verwendende Tabellennamen mitgeteilt. Fehlt diese Angabe, wird der Pluralname der Klasse als Tabellenname verwendet. 
  • Durch Hinzufügen von protected $fillable wird Eloquent angewiesen, die Massenzuweisung des Feldes einzurichten (siehe Link oben).

Als Nächstes müssen Sie den Controller erstellen, in dem Sie die für jede Anfrageroute benötigte Logik implementieren werden. Öffnen Sie erneut das Terminal und führen Sie Folgendes aus:

$ php artisan make:controller HomeController

Dadurch wird eine Controller-Datei unter app/Http/Controllers/HomeController.php mit folgendem Inhalt erstellt:

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    //
}

Methode zum Speichern der Telefonnummer erstellen

Erstellen Sie eine Funktion, die ein neues UsersPhoneNumber-Modell mit den Daten aus dem Anfragetext instanziiert:

<?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"]);
}

Im obigen Code wird eine Validierung für die Daten durchgeführt, die vom Text $request übergeben wurden, bevor eine neue Instanz von UsersPhoneNumber erstellt wird. Nach dem Speichern der Telefonnummer werden Sie wieder auf die Willkommensseite geleitet, wobei eine Erfolgsmeldung per flash an die Sitzung übergeben wird.

Ansicht mit Telefonnummern zurückgeben

Nun müssen Sie die Ansicht mit den Daten der registrierten Telefonnummern zurückgeben. Schreiben Sie eine einfache Funktion in den HomeController, mit der die Tabelle users_phone_number abgefragt wird und die Ergebnisse an die Ansicht zurückgegeben werden:

<?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
}

HINWEIS: compact() ist eine PHP-Funktion, mit der Sie ein Array mit Variablennamen und deren Werten erstellen können.

Nachrichten mit Twilio Programmable SMS senden

Im nächsten Schritt implementieren Sie den SMS-Versand mit der Bibliothek von Twilio Programmable SMS. Erstellen Sie eine private Funktion im HomeController, die als Hilfsfunktion für das Senden von Nachrichten dient:

<?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] );
}

Die Funktion empfängt zwei Parameter: $message und $recipients. Dann werden die gespeicherten Twilio-Anmeldeinformationen aus den Umgebungsvariablen mit der integrierten PHP-Funktion getenv() abgerufen und es wird ein neuer Twilio Client mit den Anmeldeinformationen instanziiert. Jetzt können Sie die SMS mit folgendem Aufruf senden:

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

Die Twilio-Funktion messages->create() nimmt zwei Parameter entgegen: den Nachrichtenempfänger und ein Array mit den Eigenschaften from und body, wobei from Ihre aktive Twilio-Telefonnummer ist.

Benutzerbenachrichtigung bei Registrierung senden

Sie haben bislang die Funktion sendMessage() fertiggestellt, mit der Sie Nachrichten an Nutzer:innen senden werden. Jetzt aktualisieren Sie die Funktion storePhoneNumber(), um Benachrichtigungen über eine erfolgreiche Registrierung zu senden. Dazu müssen Sie die Funktion storePhoneNumber() wie folgt ändern:

<?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"]);
}

Hervorragend. Wenn jetzt eine Telefonnummer zu Ihrer Datenbank hinzugefügt wird, können Sie eine entsprechende Benachrichtigung an Nutzer:innen senden.

Nutzerdefinierte Nachrichten senden

Als Nächstes schreiben Sie eine Funktion zum Senden nutzerdefinierter Nachrichten an ausgewählte Personen. Fügen Sie den folgenden Code zum HomeController hinzu:

<?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!"]);
}

Diese Funktion übergibt die validierten Daten aus dem Text von $request an die Variable $validatedData. So können Sie das Array $validatedData[users] durchlaufen und die von $validatedData["body"] erhaltene Nachricht an Nutzer:innen senden. Danach kehren Sie zur Begrüßungsseite zurück und erhalten eine Nachricht, die an die Sitzung gesendet wird.

Routen erstellen

Sie haben die Controller-Funktionen erfolgreich erstellt. Jetzt fügen Sie der Anwendung Routen hinzu. Öffnen Sie routes/web.php und nehmen Sie die folgenden Änderungen vor:

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

Formularfeld mit Routen aktualisieren

Gehen Sie nun zu resources/views/welcome.blade.php und nehmen Sie die folgenden Änderungen am Formularfeld vor:

//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>

und

//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>

Code testen

Führen Sie den gesamten Code, den Sie bisher erstellt haben, zusammen. Jetzt sollte Ihre HomeController.php wie folgt aussehen:

<?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]);
    }
}

Und für die Ansicht sollte Ihre welcome.blade.php wie folgt aussehen:

<!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>

Wenn Ihr Code derselbe ist, können Sie fortfahren. Wenn nicht, überprüfen Sie, was fehlt.

Anwendung ausführen

Öffnen Sie Ihr Terminal, navigieren Sie zum Projektverzeichnis und führen Sie den folgenden Befehl aus:

$ php artisan serve

Dadurch wird Ihre Laravel-Anwendung auf einem localhost-Port, normalerweise 8000, bereitgestellt. Öffnen Sie den nach der Ausführung des Befehls ausgedruckten localhost-Link in Ihrem Browser. Sie sollten eine Seite wie diese sehen:

Auf localhost ausgeführte Laravel-App

Registrieren Sie eine neue Telefonnummer. Sie sollten dann in Kürze eine SMS erhalten, die Sie über Ihre Registrierung informiert.

Beispiel einer Textnachricht von einem Twilio-Testkonto

 Sie können auch das Senden von nutzerdefinierten Benachrichtigungen testen. Wählen Sie dazu eine Person aus dem Auswahlfeld aus und geben Sie den Text, der an die diese Person gesendet werden soll, in das Textfeld ein. Klicken Sie dann auf die Schaltfläche „Send Notification“ (Benachrichtigung senden) und Sie sollten eine SMS mit der nutzerdefinierten Benachrichtigung erhalten.

Nutzerdefinierte Benachrichtigungen

Fazit

Nach Abschluss dieses Tutorials sollten Sie Twilio Programmable SMS in Ihre Laravel-Anwendung integrieren und Benachrichtigungen per SMS senden können. Den vollständigen Quellcode für dieses Tutorial finden Sie auf Github

Ein nächster Schritt könnte darin bestehen, dass Nutzer:innen nach erhaltener SMS-Benachrichtigung eine Aktion ausführen können. 

Wenn Sie Fragen zu diesem Tutorial haben, helfe ich Ihnen gerne weiter. Sie erreichen mich wie folgt: