Laravel Websockets 443 √ľber https - 443

Mit Hilfe von WebSockets können Echtzeit-Webanwendungen umgesetzt werden. WebSockets ermöglichen dem Browser auf bestimmte Anforderungen vom Server zu warten, der Browser muss also nicht regelmäßig nach Updates vom Server fragen, er wird vom Server aktiv informiert. 

Eine WebSockets-L√∂sung kann in Laravel mit Pusher oder socket.io implementiert werden. Hier ein einfaches Beispiel, die spezifischen Einstellungen f√ľr Pusher und ECHO mit socket.io folgen im Anschluss.

Beispiel

Der Browser erstellt mittels Javascript eine WebSocket-Verbindung zu Pusher oder einem eigenen socket.io Server.

Ich verwende dazu die URL: /eventtest

An dieser Stelle wartet der Browser auf Events vom Server.

Beim Aufruf der URL /eventfire wird ein Event ausgelöst:

Die URL /eventtest wird √ľber das Ausl√∂sen des Events informiert und regiert darauf mit einem Alert:

/routes/web.php

F√ľr den Aufruf der beiden Seiten erstellen wir 2 Routes

use App\Events\EventTrigger;

Route::view('/eventtest', 'eventListener');
route::get('/eventfire', function () {
event(new EventTrigger());
});

/eventtest lädt eine View

/eventfire lädt direkt einen Event, welchen wir wie folgt erstellen können:

Trigger

php artisan make:event EventTrigger

 /app/Events/EventTrigger.php

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class EventTrigger implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('channel-test');
    }
}

In der Datei /config/app.php muss zudem die Zeile: App\Providers\BroadcastServiceProvider::class, aktiviert werden, diese ist standardmäßig auskommentiert

ShouldBroadcast vs. ShouldBroadcastNow

ShouldBroadcast verwendet den Standard-Queue-Driver, ShouldBroadcastNow verwendet "sync" als Queue-Driver, Events werden also sofort rausgeschickt.

Sollte der Standard-Queue-Driver sync sein, macht es also keinen Unterschied ob ShouldBroadcastNow oder ShouldBroadcast verwendet wird.

Redis als Queue-Driver:

Sollte als Queue-Driver Redis zum Einsatz kommen, in der .env -Datei wird also

QUEUE_DRIVER=redis 

verwendet,¬†wird f√ľr das Abhandeln der Events noch ein laufender¬†Queue-Worker ben√∂tigt:

Konsole: php artisan queue:work redis

Wie vorhin beschrieben muss dazu ShouldBroadcast und nicht ShouldBroadcastNow in EventTrigger.php verwendet werden.

Voraussetzung ist die Installation des Redis-Servers, siehe: www.libe.net/ubuntu-redis zudem muss Redis in der .env-Datei konfiguriert werden:

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=???
REDIS_PORT=6379
permantentes Ausf√ľhren des Queue Workers:

Ubuntu/Debian sudo apt-get install supervisor

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/vhosts/domain/laravelfolder/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=root
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/vhosts/domain/laravelfolder/laravel/storage/logs/worker.log
sudo supervisorctl stop all 
sudo supervisorctl reread
sudo supervisorctl reload

Der Status kann mit

supervisorctl status

√ľberpr√ľft werden ...

/resources/views/eventListener.blade.php

<!DOCTYPE html>
<html>
  <head>
      <title>EventTest</title>
	    <link rel="stylesheet" href="/css/app.css">
	  	<meta name="csrf-token" content="{{ csrf_token() }}">
  </head>
  <body>
	<div id="app2">
		<p>test</p>
	</div>
 	<script src="/js/app.js" charset="utf-8"></script>   
 	<script>
 	new Vue({
 		el: '#app2',

 		created() {
 			Echo.channel('channel-test').listen('EventTrigger', (e) => {
 			 alert('EventTriggered');
 			};
 		}
 	});</script>
  </body>
</html>

Private

/app/Events/EventTrigger.php: PrivateChannel

<?php

namespace App\Events;
use Illuminate\Support\Facades\Auth;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;


class EventTrigger implements ShouldBroadcastNow
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    { 
        return new PrivateChannel('App.User.'.  Auth::user()->id );
    }
}

routes/channels.php - Client can not be authenticated, got HTTP status 403

Damit die Authentifizierung f√ľr private Channels √ľberpr√ľft wird, m√ľssen die User in channels.php √ľberpr√ľft werden.

Broadcast::channel('App.User.{id}', function ($user, $id) {
    return (int) $user->id === (int) $id;
});

Sollte die √úberpr√ľfung fehlschlagen, taucht im Log des Echo-Servers folgender Fehler auf:¬†Client can not be authenticated, got HTTP status 403

/resources/views/eventListener.blade.php

<!DOCTYPE html>
<html>
  <head>
      <title>EventTest</title>
	    <link rel="stylesheet" href="/css/app.css">
	  	<meta name="csrf-token" content="{{ csrf_token() }}">
  </head>
  <body> 
	<div id="app2">
		<p>test</p>
	</div>
 	<script src="/js/app.js" charset="utf-8"></script>   
	  <script>
		  const app2 = new Vue({
	el: '#app2',
	created() {
		Echo.private('App.User.{{ Auth::user()->id }}')
		.listen('EventTrigger', (e) => {
		 alert('EventTriggered');
		});
		}
	});
	 </script>
  </body>
</html>
positive Bewertung({{pro_count}})
Beitrag bewerten:
{{percentage}} % positiv
negative Bewertung({{con_count}})

DANKE f√ľr deine Bewertung!


Fragen / Kommentare