Mohamed Benhida

admin@devma.net

December 13, 2017

Real Time Chat Application

Hey ,

in this post we will talk how can we make a real time chat application.

First of all we begin by creating an account on Pusher after we creates our laravel project of course.

then we install pusher on our laravel project.

composer require pusher/pusher-php-server:~2.0

we launch npm install for installing all javascript packages comming with laravel like vuejs - axios ...

npm install --save laravel-echo pusher-js

Now that we did all the download we start the coding first all we need an event called ChatMessage.

php artisan make:event ChatMessage

Dont forget to add implements ShouldBroadcast !! On your ChatMessage class like this

class ChatMessage implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $message;
    public $userID;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($message,$userID)
    {
        $this->message = $message;
        $this->userID = $userID;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('chat'.$this->userID);
    }
}

We add the chat table where the messages will be saved.

php artisan make:model Chat -m

Schema::create('chats', function (Blueprint $table) {
            $table->increments('id');
            $table->string('message');
            $table->integer('user_id');
            $table->integer('toID');
            $table->timestamps();
        });

We add the credentials of our Pusher application that we created in .env

PUSHER_APP_ID=354771
PUSHER_APP_KEY=623f7dfb76591710354a
PUSHER_APP_SECRET=5801addc6b965e1274ab

We edit also the BROADCAST_DRIVER in .env to pusher.

BROADCAST_DRIVER=pusher

We go to config/app.php then we uncomment this line so we can use the BroadcastProvider.

App\Providers\BroadcastServiceProvider::class,

We go to config/broadcasting.php and add this

'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                 'cluster' => 'eu'
            ],

Now we go to javascript code

add Echo and pusher-js in resources/assets/js/app.js

import Echo from "laravel-echo"
window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'f49f723d762dfeda90a9',
    cluster : 'eu',
    encrypted : true
});


Vue.component('chat', require('./components/Chat.vue'));

const app = new Vue({
    el: '#app'
});

We make the default laravel authentification 

php artisan make:auth

We add the relation with chat and user table like this in User.php

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function message()
    {
        return $this->hasMany('App\Chat');
    }
}

IN web.php

Route::get('/chat/{id}', [
    'uses' => 'UserController@chat',
    'as' => 'chat'
    ]);

Auth::routes();
Route::get('/',[
    'uses' => 'UserController@getUser'
    ]);
Route::post('/add_message',[
    'uses' => 'UserController@add',
    'as' => 'add_chat'
    ]);

We create an UserController

php artisan make:controller UserController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\chat;
use Auth;
use App\Events\ChatMessage;
use App\User;
class UserController extends Controller
{

    public function __construct()
    {
        $this->middleware('auth'); //faut être connecter pour acceder à ce controller
    }
    public function chat($id)
    {
        $user = User::find($id);
        return view('chat')->with('user',$user);
    }
    public function getUser()
    {
        $user = User::take(5)->whereNotIn('id',[Auth::user()->id])->get();
        return view('getuser')->with('users',$user);
    }
    public function add(Request $request)
    {
        $user = Auth::user();
        $message = new Chat;
        $message->message = $request->message;
        $message->toID = $request->toID;
        $user->message()->save($message);
        event(new ChatMessage($message->message,$message->toID));
        return response()->json(['message' => $request->message]);
    }
}

Create a chat component on resources/assets/js/components/Chat.vue

<template>
    <div class="row">
    <div class="col-md-6 col-md-offset-3" style="margin-top:50px">
            <ul class="list-group">
                <li class="list-group-item" v-for="message in messages">{{ message.text }}</li>
            </ul>
        <div class="form-group">
            <input type="text" v-model="message" placeholder="message" class="form-control">
        </div>
        <div class="form-group">
            <button class="btn btn-primary" v-on:click="envoyer">Envoyer</button>
        </div>
        </div>
        </div>

</template>

<script>
    export default{
        props : ['toid','uid'],
        data()
        {
            return {
                message : '',
                messages : [],
                idUser : this.uid,
                idTo : this.toid
            }
        },
        mounted()
        {
            Echo.channel('chat'+this.idUser)
             .listen('ChatMessage', (e) => {
                console.log(e.message);
                this.messages.push({
                text : e.message
                });
                });
        },

        methods : {
            envoyer()
            {
                var ap = this;

                axios.post('/add_message', {
                message: this.message,
                toID : this.idTo
            })
            .then(function (response) {
                ap.messages.push({
                text : response.data.message
             });
                ap.message = '';
            })
            .catch(function (error) {
            console.log(error);
            });
            }
        }
    }
</script>

Get the available users that we can chat with them.

getuser.blade.php

@extends('layouts.app')

@section('content')

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Dashboard</div>

                <div class="panel-body">
                     <ul class="list-group">
                     @foreach($users as $user)
                <a href="{{ route('chat',$user->id) }}"><li class="list-group-item" >{{ $user->name }}</li></a>
                @endforeach
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>

@endsection

view

chat.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
<div class="col-md-6 col-md-offset-3">
    <h2 class="text-center">Envoyer Message à {{ $user->name }}</h2>
</div>
     <chat toid="{{ $user->id }}" uid="{{ Auth::user()->id }}"></chat>       
</div>
@endsection

view

 

Now two users can chat in real time you just need to open two navigators and you test.

You can find all the things that we talked about in code source Github .

© Mohamed Benhida.

Blog | Packages | About