Hi Artisan,
In this tutorial, i
will guide you step by step how to use event broadcasting using pusher and
laravel-echo-server in laravel 7 application. Laravel provide event
broadcasting topic. event broadcast is a very interesting and it's also easy to
implement with pusher specially.
In this tutorial we are going to build laravel
chat application using pusher. It will be real time chat app cause we use
broadcasting. So using broadcasting we are going to make laravel chat demo. So
let's try to complete real time chat system with laravel pusher and vue
js.
I will use vue js to to create it. So let's
start. you can read also below post to konw basic knowlege about broadcasting
and defenitily you will know how laravel broadcasting works. Let's create one
to one chat application in laravel vue js and pusher.
Read also : Real Time Event Broadcasting with Laravel 6 and Pusher
You need to just follow few step to done this
following thing. so let's follow bellow steps and done as real time chat with
laravel.
Step 1: Install Laravel 6
First of all, we need to get fresh Laravel 6
version application using bellow command because we are going from scratch, So
open your terminal OR command prompt and run bellow command:
composer
create-project --prefer-dist laravel/laravel blog
PHP
Copy
Step 2: Make auth
Laravel's laravel/ui package provides a quick way to scaffold all of the routes
and views you need for authentication using a few simple commands:
composer
require
laravel/ui --dev
php
artisan ui vue --auth
PHP
Copy
If you are
broadcasting your events over Pusher Channels,
you should install the Pusher Channels PHP SDK using the Composer package
manager: Run this below command.
composer
require
pusher/pusher-php-server "~4.0"
PHP
Copy
Step 3: Install Larave Echo
Laravel Echo is a JavaScript library that
makes it painless to subscribe to channels and listen for events broadcast by
Laravel. You may install Echo via the NPM package manager.
npm
install --save laravel-echo pusher-js
PHP
Copy
After installing it, open config/app.php file
and uncomment this following line.
config/app.php
App\Providers\BroadcastServiceProvider::class,
PHP
Copy
Now open config/broadcasting.php file and make
this changes.
config/broadcasting.php
'default' => env('BROADCAST_DRIVER', 'pusher'),
PHP
Copy
Now in laravel 6 everything should be ok. Now
we have to connect pusher with Laravel. So go to puhser and create a
new app and paste this key to .env file like below. Make sure you have changed
broadcast driver log to pusher
.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=933362
PUSHER_APP_KEY=f18ead0fa8750c93afd7
PUSHER_APP_SECRET=7d8af7728ca7242f0607
PUSHER_APP_CLUSTER=mt1
PHP
Copy
Make sure you enable client event otherwise
whisper will not work. Whisper mean using this we will identifying who are
typing now. See below image to understand.
Step 4: Setup Migration
To create our laravel chat app, we need
migration for our chat table, run below command
php
artisan make:model Chat -m
PHP
Copy
after doing it open your chats migration file
and paste this following code.
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateChatsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('chats', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id');
$table->text('message');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('chats');
}
}
PHP
Copy
Now run php artisan migrate to migrate our
table.
php
artisan migrate
PHP
Copy
Step 5: Setup Route
routes/web.php
Route::get('/chats', 'ChatController@index');
Route::get('/messages', 'ChatController@fetchAllMessages');
Route::post('/messages', 'ChatController@sendMessage');
PHP
Copy
Step 5: Setup Controller
Now open
ChatController and paste this following code.
app/Https/Controller/ChatController.php
namespace App\Http\Controllers;
use App\Chat;
use App\Events\ChatEvent;
use Illuminate\Http\Request;
class ChatController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('chat.chat');
}
public function fetchAllMessages()
{
return Chat::with('user')->get();
}
public function sendMessage(Request $request)
{
$chat
= auth()->user()->messages()->create([
'message' => $request->message
]);
broadcast(new ChatEvent($chat->load('user')))->toOthers();
return ['status' => 'success'];
}
}
PHP
Copy
When building an
application that utilizes event broadcasting, you may substitute the event function with the broadcast function.
Like the event function, the broadcast function dispatches the event to your server-side
listeners:
broadcast(new ShippingStatusUpdated($chat));
PHP
Copy
Here, the broadcast function also exposes the toOthers method which allows you to exclude the current user from
the broadcast's recipients:
broadcast(new ShippingStatusUpdated($chat))->toOthers();
PHP
Copy
Step 6: Create Event
Now we have to create our broadcasting event
to fire our broadcasting channel. To do it run following command.
php
artisan make:event ChatEvent
PHP
Copy
after running this command you will find this
file inside app/Events/ChatEvent.php path. Open it and paste this code.
app/Events/ChatEvent.php
namespace App\Events;
use App\Chat;
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 ChatEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $chat;
public function __construct(Chat $chat)
{
$this->chat = $chat;
}
public function broadcastOn()
{
return new PresenceChannel('chat');
}
}
PHP
Copy
Make sure the chatEvent of course implements
ShouldBroadcast. Now open Post model and paste this following code.
app/Chat.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Chat extends Model
{
protected $guarded = [];
public function user(){
return $this->belongsTo(User::class);
}
}
PHP
Copy
app/User.php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
public function messages(){
return $this->hasMany(Chat::class);
}
}
PHP
Copy
Step 7: Install Vue dependency and edit
configurations
Now, go inside the project folder and install
the frontend dependencies using the following command.
npm
install
PHP
Copy
now open this followng file and paste this
code. Make an asstes folder inside resources folder and copy js and sass folder
inside it. Thats all. We need it to setup our laravel mix.
Read also : Laravel Vue JS
CRUD Example With File Upload and Pagination
webpack.mix.js
const mix = require('laravel-mix');
mix.js('resources/assets/js/app.js',
'public/js/app.js')
.sass('resources/assets/sass/app.scss', 'public/css/app.css');
PHP
Copy
now create a PostComponent to create our post
and paste this code.
resources/assets/js/components/ChatComponent.vue
<template>
<div
class="row">
<div
class="col-8">
<div class="card card-default">
<div class="card-header">Messages</div>
<div class="card-body p-0">
<ul class="list-unstyled" style="height:300px; overflow-y:scroll" v-chat-scroll>
<li class="p-2" v-for="(message, index) in messages" :key="index" >
<strong>{{
message.user.name }}</strong>
{{ message.message
}}
</li>
</ul>
</div>
<input
@keydown="sendTypingEvent"
@keyup.enter="sendMessage"
v-model="newMessage"
type="text"
name="message"
placeholder="Enter your message..."
class="form-control">
</div>
<span class="text-muted" v-if="activeUser" >{{ activeUser.name
}} is typing...</span>
</div>
<div
class="col-4">
<div class="card card-default">
<div class="card-header">Active Users</div>
<div class="card-body">
<ul>
<li class="py-2" v-for="(user, index) in users" :key="index">
{{ user.name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props:['user'],
data() {
return {
messages: [],
newMessage: '',
users:[],
activeUser: false,
typingTimer: false,
}
},
created() {
this.fetchMessages();
Echo.join('chat')
.here(user => {
this.users = user;
})
.joining(user => {
this.users.push(user);
})
.leaving(user => {
this.users = this.users.filter(u => u.id !=
user.id);
})
.listen('ChatEvent',(event)
=> {
this.messages.push(event.chat);
})
.listenForWhisper('typing', user => {
this.activeUser = user;
if(this.typingTimer) {
clearTimeout(this.typingTimer);
}
this.typingTimer = setTimeout(() => {
this.activeUser = false;
}, 1000);
})
},
methods: {
fetchMessages() {
axios.get('messages').then(response => {
this.messages =
response.data;
})
},
sendMessage() {
this.messages.push({
user: this.user,
message: this.newMessage
});
axios.post('messages', {message: this.newMessage});
this.newMessage = '';
},
sendTypingEvent() {
Echo.join('chat')
.whisper('typing', this.user);
console.log(this.user.name + ' is typing now')
}
}
}
</script>
HTML
Copy
now open this file
resources/assets/js/bootstrap.js and uncomment this following line of code.
resources/assets/js/bootstrap.js
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,
encrypted: true
});
JavaScript
Copy
Install vue-chat-scroll
A plugin for Vue.js 2
that scrolls to the bottom of an element when new content is added within said
element. See demo. To install it run below command.
npm
install --save vue-chat-scroll
PHP
Copy
now open app.js file and paste this followng
code.
resources/assets/js/app.js
require('./bootstrap');
window.Vue
= require('vue');
Vue.component('chat-component', require('./components/ChatComponent.vue').default);
import VueChatScroll from 'vue-chat-scroll'
Vue.use(VueChatScroll)
const app = new Vue({
el: '#app',
});
JavaScript
Copy
Now open channels.php file to setup our
private channel.
routes/channels.php
Broadcast::channel('chat', function ($user) {
return $user;
});
PHP
Copy
Step 7: Setup blade file
Now time to setup our blade file. open
resources/layouts/app.php and paste this following code.
resources/views/layouts/app.blade.php
<!doctype
html>
<html lang="{{ str_replace('_',
'-', app()->getLocale()) }}">
<head>
<meta
charset="utf-8">
<meta
name="viewport" content="width=device-width,
initial-scale=1">
<meta
name="userId" content="{{ Auth::check() ?
Auth::user()->id : '' }}">
<meta
name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<link
href="{{ mix('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div
id="app">
<nav
class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
{{ config('app.name',
'Laravel') }}
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle
navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse
navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
</ul>
<ul class="navbar-nav ml-auto">
@guest
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">{{
__('Login') }}</a>
</li>
@if
(Route::has('register'))
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">{{
__('Register') }}</a>
</li>
@endif
@else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{
Auth::user()->name }} <span class="caret"></span>
</a>
<div class="dropdown-menu
dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{
__('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
@csrf
</form>
</div>
</li>
@endguest
</ul>
</div>
</div>
</nav>
<main
class="py-4">
@yield('content')
</main>
</div>
<script
src="{{ mix('js/app.js') }}" defer></script>
</body>
</html>
HTML
Copy
Now open resources/views/chat/chat.blade.php
file and paste this code.
resources/views/chat/chat.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<chat-component
:user="{{ auth()->user() }}"></chat-component>
</div>
@endsection
HTML
Copy
Now everything is set to go. Now just we have
to compile our all javascript file. so run below command.
npm
run dev
//or
npm
run watch
PHP
Copy
then visit this following url, Then you
see those below things if you send message.
http://localhost:8000/chats
Preview: Before
sending message
Preview: After sending
message
Preview: After one user leaving channel
Hope you enjoy this tutorial and hope it will
help you to learn Laravel Broadcasting event to create real time chat system.
Hope everything will work for you. If you find any error please share with me,
i will try to solve. That's it.
0 Comments