Come funziona Laravel Broadcasting

Oggi, esploreremo il concetto di trasmissione nel framework web di Laravel. Permette di inviare notifiche al lato client quando succede qualcosa sul lato server. In questo articolo, useremo la libreria di terze parti di Pusher per inviare notifiche al lato client.

Se hai mai desiderato inviare notifiche dal server al client quando qualcosa accade su un server in Laravel, stai cercando la funzione di trasmissione.

Ad esempio, supponiamo di aver implementato un'applicazione di messaggistica che consente agli utenti del tuo sistema di inviare messaggi a vicenda. Ora, quando l'utente A invia un messaggio all'utente B, si desidera informare l'utente B in tempo reale. È possibile visualizzare un popup o una finestra di avviso che informa l'utente B sul nuovo messaggio!

È il caso d'uso perfetto per analizzare il concetto di trasmissione in Laravel, ed è quello che implementeremo in questo articolo.

Se ti stai chiedendo come il server potrebbe inviare notifiche al client, sta usando le prese sotto il cofano per realizzarlo. Comprendiamo il flusso di base delle prese prima di approfondire l'implementazione effettiva.

  • Innanzitutto, è necessario un server che supporti il ​​protocollo web-socket e che consenta al client di stabilire una connessione socket web.
  • Potresti implementare il tuo server o utilizzare un servizio di terze parti come Pusher. Preferiremo quest'ultimo in questo articolo.
  • Il client avvia una connessione socket Web al server socket Web e riceve un identificatore univoco in caso di connessione riuscita.
  • Una volta che la connessione è andata a buon fine, il client si iscrive a determinati canali a cui vorrebbe ricevere eventi.
  • Infine, sotto il canale sottoscritto, il client registra gli eventi che vorrebbe ascoltare.
  • Ora sul lato server, quando si verifica un evento particolare, informiamo il server socket Web fornendogli il nome del canale e il nome dell'evento.
  • E infine, il server web-socket trasmette tale evento ai client registrati su quel particolare canale.

Non preoccuparti se sembra troppo in una volta sola; ne prenderai confidenza mentre ci spostiamo in questo articolo.

Successivamente, diamo un'occhiata al file di configurazione broadcast predefinito su config / broadcasting.php.

 env ('BROADCAST_DRIVER', 'log'), / * | ------------------------------------ -------------------------------------- | Collegamenti di trasmissione | ----------------------------------------------- --------------------------- | | Qui puoi definire tutte le connessioni di trasmissione che verranno utilizzate | per trasmettere eventi ad altri sistemi o tramite web socket. Esempi di | ogni tipo di connessione disponibile viene fornito all'interno di questo array. | * / 'connections' => ['pusher' => ['driver' => 'pusher', 'chiave' => env ('PUSHER_APP_KEY'), 'secret' => env ('PUSHER_APP_SECRET'), 'app_id' => env ('PUSHER_APP_ID'),], 'redis' => ['driver' => 'redis', 'connection' => 'default',], 'log' => ['driver' => 'log ',],' null '=> [' driver '=>' null ',],],];

Di default, Laravel supporta più adattatori di trasmissione nel core stesso.

In questo articolo, useremo il Pusher adattatore di trasmissione. A scopo di debug, è anche possibile utilizzare l'adattatore di registro. Certo, se stai usando il ceppo adattatore, il client non riceverà alcuna notifica di eventi e verrà registrato solo su laravel.log file.

Dalla prossima sezione in poi, ci occuperemo immediatamente dell'implementazione effettiva del caso d'uso di cui sopra.

Impostazione dei prerequisiti

Nella trasmissione, ci sono diversi tipi di canali: pubblico, privato e presenza. Quando vuoi trasmettere pubblicamente i tuoi eventi, è il canale pubblico che dovresti utilizzare. Al contrario, il canale privato viene utilizzato quando si desidera limitare le notifiche degli eventi a determinati canali privati.

Nel nostro caso d'uso, vogliamo avvisare gli utenti quando ricevono un nuovo messaggio. E per essere idoneo a ricevere le notifiche di trasmissione, l'utente deve aver effettuato l'accesso. Pertanto, nel nostro caso, dovremo utilizzare il canale privato.

Core Authentication Feature

Innanzitutto, è necessario abilitare il sistema di autenticazione Laravel predefinito in modo che funzioni quali registrazione, accesso e simili funzionino immediatamente. Se non sei sicuro di come farlo, la documentazione ufficiale fornisce una rapida panoramica di ciò.

Pusher SDK-Installazione e configurazione

Come useremo il Pusher servizio di terze parti come server web-socket, è necessario creare un account con esso e assicurarsi di disporre delle necessarie credenziali API con la registrazione del post. Se hai difficoltà a crearlo, non esitare a chiedermelo nella sezione dei commenti.

Successivamente, dobbiamo installare l'SDK PHP Pusher in modo che la nostra applicazione Laravel possa inviare notifiche di trasmissione al server socket Web Pusher.

Nella root dell'applicazione Laravel, esegui il seguente comando per installarlo come pacchetto del compositore.

$ compositore richiede pusher / pusher-php-server "~ 3.0"

Ora, cambiamo il file di configurazione broadcast per abilitare l'adattatore Pusher come nostro driver di trasmissione predefinito.

 env ('BROADCAST_DRIVER', 'pusher'), / * | ------------------------------------ -------------------------------------- | Collegamenti di trasmissione | ----------------------------------------------- --------------------------- | | Qui puoi definire tutte le connessioni di trasmissione che verranno utilizzate | per trasmettere eventi ad altri sistemi o tramite web socket. Esempi di | ogni tipo di connessione disponibile viene fornito all'interno di questo array. | * / 'connections' => ['pusher' => ['driver' => 'pusher', 'chiave' => env ('PUSHER_APP_KEY'), 'secret' => env ('PUSHER_APP_SECRET'), 'app_id' => env ('PUSHER_APP_ID'), 'opzioni' => ['cluster' => 'ap2', 'encrypted' => true],], 'redis' => ['driver' => 'redis', ' connection '=>' default ',],' log '=> [' driver '=>' log ',],' null '=> [' driver '=>' null ',],],];

Come puoi vedere, abbiamo modificato il driver di trasmissione predefinito su Pusher. Abbiamo anche aggiunto le opzioni di configurazione cluster e crittografate che dovresti avere dall'account Pusher in primo luogo.

Inoltre, sta recuperando i valori dalle variabili di ambiente. Quindi assicuriamoci di impostare le seguenti variabili in .ENV file correttamente.

BROADCAST_DRIVER = pusher PUSHER_APP_ID = YOUR_APP_ID PUSHER_APP_KEY = YOUR_APP_KEY PUSHER_APP_SECRET = YOUR_APP_SECRET

Successivamente, ho dovuto apportare alcune modifiche in un paio di file Laravel di base per renderlo compatibile con l'ultimo SDK Pusher. Ovviamente, non consiglio di apportare modifiche al framework principale, ma evidenzierò solo ciò che deve essere fatto.

Vai avanti e apri il vendor / laravel / quadro / src / Illuminate / Broadcasting / emittenti / PusherBroadcaster.php file. Basta sostituire lo snippet utilizzare Pusher; con usa Pusher \ Pusher;.

Quindi, apriamo il vendor / laravel / quadro / src / Illuminate / Broadcasting / BroadcastManager.php file e apportare una modifica simile nel seguente frammento.

restituisce nuovo PusherBroadcaster (new \ Pusher \ Pusher ($ config ['key'], $ config ['secret'], $ config ['app_id'], Arr :: get ($ config, 'opzioni', [])) );

Infine, abilitiamo il servizio di trasmissione in config / app.php rimuovendo il commento nella riga seguente.

App \ Providers \ BroadcastServiceProvider :: class,

Finora, abbiamo installato librerie specifiche per server. Nella prossima sezione, esamineremo le librerie client che devono essere installate.

Librerie di eco Pusher e Laravel: installazione e configurazione

Nella trasmissione, la responsabilità del lato client è quella di iscriversi ai canali e ascoltare gli eventi desiderati. Sotto il cofano, lo realizza aprendo una nuova connessione al server web-socket.

Fortunatamente, non è necessario implementare alcun complesso javascript per realizzarlo poiché Laravel fornisce già un'utile libreria client, Laravel Echo, che ci aiuta a gestire i socket sul lato client. Inoltre, supporta il servizio Pusher che useremo in questo articolo.

Puoi installare Laravel Echo usando il gestore pacchetti NPM. Ovviamente, è necessario installare node e npm in primo luogo se non li si possiede già. Il resto è piuttosto semplice, come mostrato nel seguente frammento.

$ npm installa laravel-echo

Quello che ci interessa è il node_modules / laravel-eco / dist / echo.js file che dovresti copiare pubblici / echo.js.

Sì, capisco, è un po 'eccessivo usare solo un singolo file JavaScript. Se non vuoi seguire questo esercizio, puoi scaricare il echo.js file dal mio GitHub.

E con questo, abbiamo finito con l'installazione delle nostre librerie client.

Impostazione file back-end

Ricordiamo che stavamo parlando della configurazione di un'applicazione che consente agli utenti della nostra applicazione di inviare messaggi tra loro. D'altra parte, invieremo notifiche di trasmissione agli utenti che hanno effettuato l'accesso quando ricevono un nuovo messaggio da altri utenti.

In questa sezione creeremo i file necessari per implementare il caso d'uso che stiamo cercando.

Per cominciare, creiamo il Messaggio modello che tiene reciprocamente i messaggi inviati dagli utenti.

$ php artisan make: model Message --migration

Abbiamo anche bisogno di aggiungere alcuni campi come a, a partire dal e Messaggio alla nostra tabella dei messaggi. Quindi cambiamo il file di migrazione prima di eseguire il comando migrate.

incrementi ( 'id'); $ table-> intero ('from', FALSE, TRUE); $ table-> integer ('to', FALSE, TRUE); $ Tavola-> testo ( 'messaggio'); $ Tavola-> timestamp (); );  / ** * Invertire le migrazioni. * * @return void * / public function down () Schema :: dropIfExists ('messages'); 

Ora, eseguiamo il comando migrate che crea la tabella dei messaggi nel database.

$ php artisan migrate

Ogni volta che vuoi generare un evento personalizzato in Laravel, devi creare una classe per quell'evento. In base al tipo di evento, Laravel reagisce di conseguenza e intraprende le azioni necessarie.

Se l'evento è un evento normale, Laravel chiama le classi di ascolto associate. D'altra parte, se l'evento è di tipo broadcast, Laravel invia quell'evento al server web-socket configurato nel config / broadcasting.php file.

Poiché nel nostro esempio utilizziamo il servizio Pusher, Laravel invierà eventi al server Pusher.

Usiamo il seguente comando artisan per creare una classe evento personalizzata-NewMessageNotification.

$ php artisan make: evento NewMessageNotification

Quello dovrebbe creare il app / Eventi / NewMessageNotification.php classe. Sostituiamo il contenuto di quel file con il seguente.

messaggio = $ messaggio;  / ** * Ottieni i canali su cui l'evento dovrebbe essere trasmesso. * * @return Canale | array * / public function broadcastOn () return new PrivateChannel ('user.'. $ this-> message-> to); 

La cosa importante da notare è che il NewMessageNotification la classe implementa il ShouldBroadcastNow interfaccia. Quindi, quando solleviamo un evento, Laravel sa che questo evento dovrebbe essere trasmesso.

In effetti, potresti anche implementare il ShouldBroadcast interfaccia e Laravel aggiunge un evento nella coda degli eventi. Verrà elaborato dall'operatore della coda degli eventi quando avrà la possibilità di farlo. Nel nostro caso, vogliamo trasmetterlo subito, ed è per questo che abbiamo usato il ShouldBroadcastNow interfaccia.

Nel nostro caso, vogliamo visualizzare un messaggio che l'utente ha ricevuto, e quindi abbiamo passato il Messaggio modello nell'argomento costruttore. In questo modo, i dati verranno passati insieme all'evento.

Avanti, c'è il broadcastOn metodo che definisce il nome del canale su cui verrà trasmesso l'evento. Nel nostro caso, abbiamo utilizzato il canale privato perché vogliamo limitare la trasmissione degli eventi agli utenti che hanno effettuato l'accesso.

Il $ This-> message-> a variabile si riferisce all'ID dell'utente a cui verrà trasmesso l'evento. Pertanto, rende efficace il nome del canale utente. USER_ID.

Nel caso di canali privati, il client deve autenticarsi prima di stabilire una connessione con il server socket Web. Si assicura che gli eventi trasmessi su canali privati ​​vengano inviati solo ai client autenticati. Nel nostro caso, significa che solo gli utenti loggati potranno iscriversi al nostro canale utente. USER_ID.

Se stai utilizzando la libreria client di Laravel Echo per l'iscrizione al canale, sei fortunato! Si occupa automaticamente della parte di autenticazione e devi solo definire i percorsi del canale.

Andiamo avanti e aggiungere un percorso per il nostro canale privato nel percorsi / channels.php file.

id === (int) $ id; ); Broadcast :: channel ('user. ToUserId', function ($ user, $ toUserId) return $ user-> id == $ toUserId;);

Come puoi vedere, abbiamo definito il utente. toUserId percorso per il nostro canale privato.

Il secondo argomento del metodo del canale dovrebbe essere una funzione di chiusura. Laravel passa automaticamente l'utente attualmente loggato come primo argomento della funzione di chiusura, e il secondo argomento viene solitamente recuperato dal nome del canale.

Quando il client tenta di iscriversi al canale privato utente. USER_ID, la libreria di Laravel Echo esegue l'autenticazione necessaria in background utilizzando l'oggetto XMLHttpRequest o più comunemente noto come XHR.

Finora, abbiamo finito con il setup, quindi andiamo avanti e testarlo.

Impostazione file front-end

In questa sezione creeremo i file necessari per testare il nostro caso d'uso.

Andiamo avanti e creare un file di controller su App / HTTP / Controller / MessageController.php con i seguenti contenuti.

middleware ( 'auth');  public function index () $ user_id = Auth :: user () -> id; $ data = array ('user_id' => $ user_id); visualizzazione di ritorno ('broadcast', $ data);  public function send () // ... // messaggio viene inviato $ message = new Message; $ message-> setAttribute ('from', 1); $ message-> setAttribute ('a', 2); $ message-> setAttribute ('message', 'Demo message from user 1 to user 2'); $ Message-> save (); // desidera trasmettere l'evento evento NewMessageNotification (new NewMessageNotification ($ message)); // ...

Nel indice metodo, stiamo usando il trasmissione vista, quindi creiamo il Resources / views / broadcast.blade.php guarda anche il file.

        Test     
La nuova notifica verrà avvisata in tempo reale!

E, naturalmente, dobbiamo aggiungere percorsi anche nel percorsi / web.php file.

Route :: get ('message / index', 'MessageController @ index'); Route :: get ('message / send', 'MessageController @ send');

Nel metodo del costruttore della classe controller, puoi vedere che abbiamo usato il auth middleware per assicurarsi che i metodi del controller siano accessibili solo dagli utenti loggati.

Avanti, c'è il indice metodo che rende il trasmissione vista. Inseriamo il codice più importante nel file di visualizzazione.

    

In primo luogo, carichiamo le librerie client necessarie, Laravel Echo e Pusher, permettendoci di aprire la connessione web-socket al server socket Web Pusher.

Successivamente, creiamo l'istanza di Echo fornendo Pusher come nostro adattatore di trasmissione e altre informazioni relative al Pusher necessarie.

Andando oltre, usiamo il metodo privato di Echo per iscriversi al canale privato utente. USER_ID. Come discusso in precedenza, il client deve autenticarsi prima di iscriversi al canale privato. Quindi il Eco oggetto esegue l'autenticazione necessaria inviando l'XHR in background con i parametri necessari. Finalmente, Laravel prova a trovare il utente. USER_ID percorso, e dovrebbe corrispondere al percorso che abbiamo definito nel percorsi / channels.php file.

Se tutto va bene, dovresti avere una connessione web-socket aperta con il server web-socket Pusher, ed elencare gli eventi sul utente. USER_ID canale! D'ora in poi, saremo in grado di ricevere tutti gli eventi in arrivo su questo canale.

Nel nostro caso, vogliamo ascoltare il NewMessageNotification evento e quindi abbiamo usato il ascolta metodo del Eco oggetto di raggiungerlo. Per semplificare le cose, avvertiremo semplicemente il messaggio che abbiamo ricevuto dal server Pusher.

Quindi questa era la configurazione per ricevere eventi dal server web-socket. Successivamente, passeremo attraverso il inviare metodo nel file controller che solleva l'evento broadcast.

Inseriamo rapidamente il codice di inviare metodo.

funzione pubblica send () // ... // messaggio viene inviato $ message = new Message; $ message-> setAttribute ('from', 1); $ message-> setAttribute ('a', 2); $ message-> setAttribute ('message', 'Demo message from user 1 to user 2'); $ Message-> save (); // desidera trasmettere l'evento evento NewMessageNotification (new NewMessageNotification ($ message)); // ...

Nel nostro caso, notificheremo agli utenti che hanno effettuato l'accesso quando ricevono un nuovo messaggio. Quindi abbiamo cercato di imitare quel comportamento nel inviare metodo.

Successivamente, abbiamo usato il evento funzione di aiuto per aumentare il NewMessageNotification evento. Dal momento che il NewMessageNotification l'evento è di ShouldBroadcastNow digita, Laravel carica la configurazione di trasmissione predefinita da config / broadcasting.php file. Infine, trasmette il NewMessageNotification evento al server Web-socket configurato sul utente. USER_ID canale.

Nel nostro caso, l'evento verrà trasmesso al server web-socket Pusher sul utente. USER_ID canale. Se l'ID dell'utente destinatario è 1, l'evento sarà trasmesso su user.1 canale.

Come abbiamo discusso in precedenza, abbiamo già una configurazione che ascolta gli eventi su questo canale, quindi dovrebbe essere in grado di ricevere questo evento e la casella di avviso viene visualizzata all'utente!

Andiamo avanti e spieghiamo come si suppone di testare il caso d'uso che abbiamo costruito finora.

Apri l'URL http: // your-laravel-site-domain / message / index nel tuo browser. Se non hai ancora effettuato l'accesso, verrai reindirizzato alla schermata di accesso. Una volta effettuato l'accesso, dovresti vedere la visualizzazione broadcast che abbiamo definito in precedenza, non ancora niente di speciale.

In effetti, Laravel ha già fatto un bel po 'di lavoro in background per te. Come abbiamo abilitato il Pusher.logToConsole impostazione fornita dalla libreria client Pusher, registra tutto nella console del browser per scopi di debug. Vediamo cosa viene registrato sulla console quando si accede alla pagina http: // your-laravel-site-domain / message / index.

Pusher: stato modificato: inizializzato -> collegamento Pusher: Connessione: "transport": "ws", "url": "wss: //ws-ap2.pusher.com: 443 / app / c91c1b7e8c6ece46053b? Protocol = 7 & client = js & versione = 4.1.0 & flash = false " Pusher: Connessione: " transport ":" xhr_streaming "," url ":" https://sockjs-ap2.pusher.com:443/pusher/app/c91c1b7e8c6ece46053b?protocol=7&client= js & version = 4.1.0 " Pusher: stato modificato: connessione -> connesso con nuovo ID socket 1386.68660 Pusher: evento inviato: " evento ":" pusher: subscribe "," data ": " auth ":" c91c1b7e8c6ece46053b: cd8b924580e2cbbd2977fd4ef0d41f1846eb358e9b7c327d89ff6bdc2de9082d "," channel ":" private-user.2 " Pusher: Event recd: " event ":" pusher_internal: subscription_succeeded "," data ": ," channel ":" private-user.2 " Pusher: nessuna callback su private-user.2 per pusher: subscription_succected

Ha aperto la connessione web-socket con il server web-socket Pusher e si è iscritto per ascoltare gli eventi sul canale privato. Naturalmente, potresti avere un nome di canale diverso nel tuo caso in base all'ID dell'utente con cui hai effettuato l'accesso. Ora, teniamo aperta questa pagina mentre ci spostiamo per testare il inviare metodo.

Quindi, apriamo http: // your-laravel-site-domain / message / send URL nell'altra scheda o in un altro browser. Se stai per utilizzare un browser diverso, devi accedere per poter accedere a quella pagina.

Non appena apri la pagina http: // your-laravel-site-domain / message / send, dovresti essere in grado di vedere un messaggio di avviso nell'altra scheda all'indirizzo http: // your-laravel-site-domain / message /indice.

Passiamo alla console per vedere cosa è appena successo.

Pusher: Event recd: "event": "App \\ Events \\ NewMessageNotification", "data": "message": "id": 57, "from": 1, "a": 2, "messaggio ":" Demo messaggio da utente 1 a utente 2 "," created_at ":" 2018-01-13 07:10:10 "," updated_at ":" 2018-01-13 07:10:10 "," canale ":" private-user.2" 

Come puoi vedere, ti dice che hai appena ricevuto il App \ Eventi \ NewMessageNotification evento dal server socket Web Pusher sul private-user.2 canale.

In effetti, puoi vedere cosa sta succedendo là fuori anche alla fine del Pusher. Vai al tuo account Pusher e vai alla tua applicazione. Sotto il mettere a punto consolle, dovresti essere in grado di vedere i messaggi registrati.

E questo ci porta alla fine di questo articolo! Spero che non sia stato un granché in un solo tentativo, visto che ho cercato di semplificare le cose al meglio delle mie conoscenze.

Conclusione

Oggi abbiamo analizzato una delle funzioni meno discusse della trasmissione di Laravel. Ti consente di inviare notifiche in tempo reale tramite socket web. Nel corso di questo articolo, abbiamo creato un esempio del mondo reale che ha dimostrato il concetto di cui sopra.

.