Creating Real Time Notifications in Laravel with Laravel Web Sockets

Creating Real Time Notifications in Laravel with Laravel Web Sockets

In this post we will be looking at how to build a realtime notification Laravel App with Laravel Websockets and Echo.

This could be used to send realtime notifications to a user about an order dispatched, new post, comments or many other reasons.

Code here is you need. Repo

Create an App

laravel new realtime-notifications-app && cd realtime-notifications-app

Run the App

php -S localhost:8000 -t public

Install the Packages

composer require beyondcode/laravel-websockets

composer require pusher/pusher-php-server

Edit .ENV file

Used by the package we don't use Pusher but needs configuring, don't forget to make these more secure in production.

BROADCAST_DRIVER=pusher

PUSHER_APP_ID=98765

PUSHER_APP_KEY=98765

PUSHER_APP_SECRET=98765

PUSHER_APP_CLUSTER=mt1

Publish the package migrations

php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"

Database

Get your DB set up in .env and then run the migrations

php artisan migrate

Publish the Package Config

php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"

Launch the Stats Page

Go to http://localhost:8000/laravel-websockets and you should now see:

Web socket not connected

 

Click the connect button and you should get the following:

Connected to websocket

 

Create an Event

php artisan make:event RealTimePost

Edit the Event to match the following:

use Illuminate\Broadcasting\Channel;

use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

use Illuminate\Queue\SerializesModels;

class RealTimePost implements ShouldBroadcast

{

    use SerializesModels;

    public string $message;

    public function __construct(string $message)

    {

        $this->message = $message;

    }




    public function broadcastOn(): Channel

    {

        return new Channel('events');

    }

}

Broadcasting

Change the broadcasting.php config file to match:

'options' => [

                'cluster' => env('PUSHER_APP_CLUSTER'),

                'encrypted' => false,

                'host' => '127.0.0.1',

                'port' => 6001,

                'scheme' => 'http'

            ],

Open tinker. php artisan tinker and run the following:

event(new App\Events\RealTimePost('Hello World'));

In your web sockets dashboard you should now see this:

Web Socket Post

Front End

npm install

npm install --save-dev laravel-echo pusher-js

Go to resources/js/bootstrap.js and add the following:

import Echo from 'laravel-echo';

 

window.Pusher = require('pusher-js');

 

window.Echo = new Echo({

    broadcaster: 'pusher',

    key: process.env.MIX_PUSHER_APP_KEY,

    cluster: process.env.MIX_PUSHER_APP_CLUSTER,

    forceTLS: false,

    wsHost: window.location.hostname,

    wsPort: 6001,

    disabledStats: true, 

    enabledTransport: [‘ws’, ‘wss’]

})

For simplicity lets just edit our welcome.php blade. Add this to just before the <body> tags and also import the app.js into your welcome page:

 

<script> Echo.channel('events') .listen('RealTimePost', (e) => console.log('RealTimePost: ' + e.message)); </script>

 

Finally run npm run dev

Go to http://localhost:8000/ and you will now see the following in your websockets dashboard:

 

Websockets

Congrats you are now connected to the websocket.

 

Now in tinker. Run the event(new App\Events\RealTimePost('Hello World')); and you will see it in your browser console.

 

 

Private Messaging

So the notifications above are broadcast to everyone. Lets make a private channel between the server and the logged in user.

In your RealTimePost Event. Change to the following:

use Illuminate\Broadcasting\PrivateChannel;

public function broadcastOn(): Channel {

    return new PrivateChannel('events');

}

Restart Tinker and resend the Event.

Private Message

 

Now in your welcome.blade. Change the Echo to:

Echo.private('events') .listen('RealTimePost', (e) => console.log('Private RealTimePost: ' + e.message));

When you refresh you will get an error in the console this is normal. In your app config file uncomment the app config file. Uncomment the line App\Providers\BroadcastServiceProvider::class and then run php artisan config:cache.

At the top of your welcome.blade file add the Laravel CSRF tags in the meta data:

 

Go to routes/channels.php and paste the following:

 

Broadcast::channel('events', function ($user) 



    return true; 

});

Now in Tinker run the following to create a new user:

 

User::create([

    'name' => 'Test Person',

    'email' => 'test@example.com',

    'password' => bcrypt('password'),

]);

 

In your routes/web.php file change the welcome route to this:

Route::get('/', function () {

    auth()->login(User::first());

 

    return view('welcome');

});

 

Remember to add use App\Models\User; to the top of the page.

 

Reload the browser and run the Tinker command and you should now receive the private notification in the console.

 

Notifications

Lets change the event to a notification.

php artisan make:notification RealTimeNotification

Open up the Notification and paste the following:

namespace App\Notifications;

 

use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

use Illuminate\Notifications\Messages\BroadcastMessage;

use Illuminate\Notifications\Notification;

 

class RealTimeNotification extends Notification implements ShouldBroadcast

{

 

    public string $message;

 

    public function __construct(string $message)

    {

        $this->message = $message;

    }

 

    public function via($notifiable): array

    {

        return ['broadcast'];

    }

 

    public function toBroadcast($notifiable): BroadcastMessage

    {

        return new BroadcastMessage([

            'message' => "$this->message (User $notifiable->id)"

        ]);

    }

}

Go back to Tinker and run the following:

$user = User::first();

Then:

$user->notify(new App\Notifications\RealTimeNotification('Hello World'));

In your websocket dashboard you should now see this:

Private Websocket

Open the welcome.blade and change the Echo to look like this:

Echo.private('App.Models.User.1') .notification((notification) => { console.log(notification.message); });

Refresh your browser with the welcome page. And run your tinker notification again and you should see an output.

The validation for the user is in the channels.php file using this line, this allows you to only show the message to the correct user:

Broadcast::channel('App.Models.User.{id}', function ($user, $id) {

    return (int) $user->id === (int) $id;

});

Code here is you need. Repo

Categories: Posts