In this tutorial we will implement a real time chat application using laravel framework and laravel broadcasting using the pusher library as it supports a real time events and channels.
Laravel broadcasting based internally on Web Sockets but the advantages of using it is that it facilitates all the hard work of web sockets because implementing web sockets from scratch require a lot of work like special server to handle connections etc, you can read more about implementing a socket server in this article.
In fact laravel handles broadcasting using the event listener pattern so before starting you should have knowledge of laravel events and listeners you can more about them here.
There are a variety of drivers that can be used inside broadcasting some of them are pusher, redis, and log. In this tutorial we will be using Pusher.
Preparing The App
Let’s create a new laravel project, in this tutorial i will be using laravel 5.5 so initiate this command in the terminal:
composer create-project laravel/laravel chat "5.5.*" --prefer-dist
After create a new database and update your .env file with the database credentials like that:
DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=<put your db name> DB_USERNAME=<put your db username> DB_PASSWORD=<put your db password>
Â
Creating Tables
When thinking about the tables, we need two have a users table and another table for the messages, fortunately laravel provides the users migration out of the box, so all we need is a messages migration:
php artisan make:migration create_messages_table
Next open database/migrations/xxxxx_create_migrations_table.php and update it as shown below:
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateMessagesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('messages', function (Blueprint $table) { $table->increments('id'); $table->unsignedInteger('from_user'); $table->unsignedInteger('to_user'); $table->text('content'); $table->timestamps(); $table->foreign('from_user')->references('id')->on('users'); $table->foreign('to_user')->references('id')->on('users'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('messages'); } }
Now run
php artisan migrate
After creating the tables let’s proceed to prepare the models.
Â
Creating Models
As we already have a User model we need only to create a new model for the messages table so initiate this command in the terminal:
php artisan make:model Message
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Message extends Model { protected $table = "messages"; }
Note there is no need to create a model for users as laravel already created to us out of the box.
Generating Authentication
Run this command to generate authentication scaffolding:
php artisan make:auth
Now the auth routes be sure that the redirectTo in LoginController, RegisterController, and ResetPasswordController like this:
protected $redirectTo = '/';
Preparing Pusher
To get the pusher credentials go to https://pusher.com/ and create a new account, then create a new app and get the credentials as shown in this image and update your .env file.
PUSHER_APP_ID=<insert app id> PUSHER_APP_KEY=<insert app key> PUSHER_APP_SECRET=<insert app secret> PUSHER_APP_CLUSTER=<insert cluster>
Preparing Chat UI
We will use bootstrap for that, a chat box contains the messages in the top and text input along with a button in the bottom area in much the same way the facebook chat looks like as shown in this image:
Project Structure
As you see in the image above this is our project file structure, so let’s first create
app/Lib/PusherFactory.php
<?php namespace App\Lib; use Pusher\Pusher; class PusherFactory { public static function make() { return new Pusher( env("PUSHER_APP_KEY"), // public key env("PUSHER_APP_SECRET"), // Secret env("PUSHER_APP_ID"), // App_id array( 'cluster' => env("PUSHER_APP_CLUSTER"), // Cluster 'encrypted' => true, ) ); } }
This simple class just return a new instance of Pusher to be used by other classes to subscribe and fire events.
create a new css file public/css/chat.css and update it like this:
p { font-size: 13px; padding: 5px; border-radius: 3px; } .base_receive p { background: #4bdbe6; } .base_sent p { background: #e674a8; } time { font-size: 11px; font-style: italic; } #login-box { margin-top: 20px } #chat_box { position: fixed; top: 10%; right: 5%; width: 27%; } .close-chat { margin-top: -17px; cursor: pointer; } .chat_box { margin-right: 25px; width: 310px; } .chat-area { height: 400px; overflow-y: scroll; } #users li { margin-bottom: 5px; } #chat-overlay { position: fixed; right: 0%; bottom: 0%; } .glyphicon-ok { color: #42b7dd; } .loader { -webkit-animation: spin 1000ms infinite linear; animation: spin 1000ms infinite linear; } @-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } }
For the sound and avatar you can download them from here.
Updating main layout
Open resources/views/layouts/app.blade.php and update it like below:
<!DOCTYPE html> <html lang="{{ app()->getLocale() }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>Chat App</title> <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <link rel="stylesheet" href="{{ asset('css/chat.css') }}" /> <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script> <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script> <script> var base_url = '{{ url("/") }}'; </script> </head> <body> <div class="container-fluid"> @yield('content') </div> <div id="chat-overlay" class="row"></div> <audio id="chat-alert-sound" style="display: none"> <source src="{{ asset('sound/facebook_chat.mp3') }}" /> </audio> @yield('script') </body> </html>
This is a simple layout we just added a div with id=’chat-verlay‘ this div will contain the chat boxes and also added audio element that represent the chat alert sound.
Next create a new view resources/views/chat-box.blade.php
<div id="chat_box" class="chat_box pull-right" style="display: none"> <div class="row"> <div class="col-xs-12 col-md-12"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title"><span class="glyphicon glyphicon-comment"></span> Chat with <i class="chat-user"></i> </h3> <span class="glyphicon glyphicon-remove pull-right close-chat"></span> </div> <div class="panel-body chat-area"> </div> <div class="panel-footer"> <div class="input-group form-controls"> <textarea class="form-control input-sm chat_input" placeholder="Write your message here..."></textarea> <span class="input-group-btn"> <button class="btn btn-primary btn-sm btn-chat" type="button" data-to-user="" disabled> <i class="glyphicon glyphicon-send"></i> Send</button> </span> </div> </div> </div> </div> </div> <input type="hidden" id="to_user_id" value="" /> </div>
The code above represents a blueprint of the chat box template, this template will be cloned according to the selected user.
Displaying home users
As we enter into a chat application we first see a list of users to chat with so let’s display them now:
open app/Http/Controllers/HomeController.php and update it like this:
<?php namespace App\Http\Controllers; use App\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth'); } /** * Show the application dashboard. * * @return \Illuminate\Http\Response */ public function index() { $users = User::where('id', '!=', Auth::user()->id)->get(); return view('home', compact('users')); } }
Then update the routes/web.php as follows:
Route::get('/', 'HomeController@index'); Auth::routes();
Finally update resources/views/home.blade.php with this code:
@extends('layouts.app') @section('content') <div class="row"> <div class="col-md-5"> @if($users->count() > 0) <h3>Pick a user to chat with</h3> <ul id="users"> @foreach($users as $user) <li><span class="label label-info">{{ $user->name }}</span> <a href="javascript:void(0);" class="chat-toggle" data-id="{{ $user->id }}" data-user="{{ $user->name }}">Open chat</a></li> @endforeach </ul> @else <p>No users found! try to add a new user using another browser by going to <a href="{{ url('register') }}">Register page</a></p> @endif </div> </div> @include('chat-box') <input type="hidden" id="current_user" value="{{ \Auth::user()->id }}" /> <input type="hidden" id="pusher_app_key" value="{{ env('PUSHER_APP_KEY') }}" /> <input type="hidden" id="pusher_cluster" value="{{ env('PUSHER_APP_CLUSTER') }}" /> @stop @section('script') <script src="https://js.pusher.com/4.1/pusher.min.js"></script> <script src="{{ asset('js/chat.js') }}"></script> @stop
As shown above we looped over the users to display them a long with a link that will open the chat box, currently you will see no users but try to register new users using a another browser. We also included the chat-box template and pusher javascript api and some hidden fields to be used by our javascript code.
Opening the chat box
Create a new controller called MessagesController so run this command in the terminal:
php artisan make:controller MessagesController
Now open app/Http/Controllers/MessagesController.php and update it as shown below:
<?php namespace App\Http\Controllers; use App\Lib\PusherFactory; use App\Message; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class MessagesController extends Controller { public function __construct() { $this->middleware('auth'); } /** * getLoadLatestMessages * * * @param Request $request */ public function getLoadLatestMessages(Request $request) { if(!$request->user_id) { return; } $messages = Message::where(function($query) use ($request) { $query->where('from_user', Auth::user()->id)->where('to_user', $request->user_id); })->orWhere(function ($query) use ($request) { $query->where('from_user', $request->user_id)->where('to_user', Auth::user()->id); })->orderBy('created_at', 'ASC')->limit(10)->get(); $return = []; foreach ($messages as $message) { $return[] = view('message-line')->with('message', $message)->render(); } return response()->json(['state' => 1, 'messages' => $return]); } }
In the code above we first create a new action getLoadLatestMessages, this action will be called when we open the chat box for the first time to fetch the latest messages between the two users.
Open resources/views/message-line.blade.php and update it as follows:
@if($message->from_user == \Auth::user()->id) <div class="row msg_container base_sent" data-message-id="{{ $message->id }}"> <div class="col-md-10 col-xs-10"> <div class="messages msg_sent text-right"> <p>{!! $message->content !!}</p> <time datetime="{{ date("Y-m-dTH:i", strtotime($message->created_at->toDateTimeString())) }}">{{ $message->fromUser->name }} • {{ $message->created_at->diffForHumans() }}</time> </div> </div> <div class="col-md-2 col-xs-2 avatar"> <img src="{{ url('images/user-avatar.png') }}" width="50" height="50" class="img-responsive"> </div> </div> @else <div class="row msg_container base_receive" data-message-id="{{ $message->id }}"> <div class="col-md-2 col-xs-2 avatar"> <img src="{{ url('images/user-avatar.png') }}" width="50" height="50" class=" img-responsive "> </div> <div class="col-md-10 col-xs-10"> <div class="messages msg_receive text-left"> <p>{!! $message->content !!}</p> <time datetime="{{ date("Y-m-dTH:i", strtotime($message->created_at->toDateTimeString())) }}">{{ $message->fromUser->name }} • {{ $message->created_at->diffForHumans() }}</time> </div> </div> </div> @endif
The above code represents a single message sent or received by the user.
update routes/web.php:
Route::get('/', 'HomeController@index'); Route::get('/load-latest-messages', 'MessagesController@getLoadLatestMessages'); Auth::routes();
Finally we need to update public/js/chat.js with this code:
$(function () { let pusher = new Pusher($("#pusher_app_key").val(), { cluster: $("#pusher_cluster").val(), encrypted: true }); let channel = pusher.subscribe('chat'); // on click on any chat btn render the chat box $(".chat-toggle").on("click", function (e) { e.preventDefault(); let ele = $(this); let user_id = ele.attr("data-id"); let username = ele.attr("data-user"); cloneChatBox(user_id, username, function () { let chatBox = $("#chat_box_" + user_id); if(!chatBox.hasClass("chat-opened")) { chatBox.addClass("chat-opened").slideDown("fast"); loadLatestMessages(chatBox, user_id); chatBox.find(".chat-area").animate({scrollTop: chatBox.find(".chat-area").offset().top + chatBox.find(".chat-area").outerHeight(true)}, 800, 'swing'); } }); }); // on close chat close the chat box but don't remove it from the dom $(".close-chat").on("click", function (e) { $(this).parents("div.chat-opened").removeClass("chat-opened").slideUp("fast"); }); }); /** * loaderHtml * * @returns {string} */ function loaderHtml() { return '<i class="glyphicon glyphicon-refresh loader"></i>'; } /** * getMessageSenderHtml * * this is the message template for the sender * * @param message * @returns {string} */ function getMessageSenderHtml(message) { return ` <div class="row msg_container base_sent" data-message-id="${message.id}"> <div class="col-md-10 col-xs-10"> <div class="messages msg_sent text-right"> <p>${message.content}</p> <time datetime="${message.dateTimeStr}"> ${message.fromUserName} • ${message.dateHumanReadable} </time> </div> </div> <div class="col-md-2 col-xs-2 avatar"> <img src="` + base_url + '/images/user-avatar.png' + `" width="50" height="50" class="img-responsive"> </div> </div> `; } /** * getMessageReceiverHtml * * this is the message template for the receiver * * @param message * @returns {string} */ function getMessageReceiverHtml(message) { return ` <div class="row msg_container base_receive" data-message-id="${message.id}"> <div class="col-md-2 col-xs-2 avatar"> <img src="` + base_url + '/images/user-avatar.png' + `" width="50" height="50" class="img-responsive"> </div> <div class="col-md-10 col-xs-10"> <div class="messages msg_receive text-left"> <p>${message.content}</p> <time datetime="${message.dateTimeStr}"> ${message.fromUserName} • ${message.dateHumanReadable} </time> </div> </div> </div> `; } /** * cloneChatBox * * this helper function make a copy of the html chat box depending on receiver user * then append it to 'chat-overlay' div * * @param user_id * @param username * @param callback */ function cloneChatBox(user_id, username, callback) { if($("#chat_box_" + user_id).length == 0) { let cloned = $("#chat_box").clone(true); // change cloned box id cloned.attr("id", "chat_box_" + user_id); cloned.find(".chat-user").text(username); cloned.find(".btn-chat").attr("data-to-user", user_id); cloned.find("#to_user_id").val(user_id); $("#chat-overlay").append(cloned); } callback(); } /** * loadLatestMessages * * this function called on load to fetch the latest messages * * @param container * @param user_id */ function loadLatestMessages(container, user_id) { let chat_area = container.find(".chat-area"); chat_area.html(""); $.ajax({ url: base_url + "/load-latest-messages", data: {user_id: user_id, _token: $("meta[name='csrf-token']").attr("content")}, method: "GET", dataType: "json", beforeSend: function () { if(chat_area.find(".loader").length == 0) { chat_area.html(loaderHtml()); } }, success: function (response) { if(response.state == 1) { response.messages.map(function (val, index) { $(val).appendTo(chat_area); }); } }, complete: function () { chat_area.find(".loader").remove(); } }); }
This code is strait forward first we created a new pusher instance and subscribed to the chat channel, we will supply this channel in the server code shortly then we added a handler for chat-toggle link. The process is to make a copy of the chatbox html template according to the selected user exactly like facebook chat when you click on any user a chat box opened, so we accomplished this by using this function:
function cloneChatBox(user_id, username, callback) { if($("#chat_box_" + user_id).length == 0) { let cloned = $("#chat_box").clone(true); // change cloned box id cloned.attr("id", "chat_box_" + user_id); cloned.find(".chat-user").text(username); cloned.find(".btn-chat").attr("data-to-user", user_id); cloned.find("#to_user_id").val(user_id); $("#chat-overlay").append(cloned); } callback(); }
After we cloned and opened the chat box we loaded the latest messages between the currently logged in user and the selected user using loadLatestMessages function.
Sending and receiving messages:
Open app/Http/Controllers/MessagesController.php and add this method:
/** * postSendMessage * * @param Request $request */ public function postSendMessage(Request $request) { if(!$request->to_user || !$request->message) { return; } $message = new Message(); $message->from_user = Auth::user()->id; $message->to_user = $request->to_user; $message->content = $request->message; $message->save(); // prepare some data to send with the response $message->dateTimeStr = date("Y-m-dTH:i", strtotime($message->created_at->toDateTimeString())); $message->dateHumanReadable = $message->created_at->diffForHumans(); $message->fromUserName = $message->fromUser->name; $message->from_user_id = Auth::user()->id; $message->toUserName = $message->toUser->name; $message->to_user_id = $request->to_user; PusherFactory::make()->trigger('chat', 'send', ['data' => $message]); return response()->json(['state' => 1, 'data' => $message]); }
In the above method, the most important part is pusherFactory::make()->trigger(), the trigger fires a new event with data and it takes three parameters [channel name, event name, array of data].
Now update routes/web.php:
<?php Route::get('/', 'HomeController@index'); Route::get('/load-latest-messages', 'MessagesController@getLoadLatestMessages'); Route::post('/send', 'MessagesController@postSendMessage'); Auth::routes();
Finally update public/js/chat.js:
$(function () { .... // on change chat input text toggle the chat btn disabled state $(".chat_input").on("change keyup", function (e) { if($(this).val() != "") { $(this).parents(".form-controls").find(".btn-chat").prop("disabled", false); } else { $(this).parents(".form-controls").find(".btn-chat").prop("disabled", true); } }); // on click the btn send the message $(".btn-chat").on("click", function (e) { send($(this).attr('data-to-user'), $("#chat_box_" + $(this).attr('data-to-user')).find(".chat_input").val()); }); // listen for the send event, this event will be triggered on click the send btn channel.bind('send', function(data) { displayMessage(data.data); }); }); /** * send * * this function is the main function of chat as it send the message * * @param to_user * @param message */ function send(to_user, message) { let chat_box = $("#chat_box_" + to_user); let chat_area = chat_box.find(".chat-area"); $.ajax({ url: base_url + "/send", data: {to_user: to_user, message: message, _token: $("meta[name='csrf-token']").attr("content")}, method: "POST", dataType: "json", beforeSend: function () { if(chat_area.find(".loader").length == 0) { chat_area.append(loaderHtml()); } }, success: function (response) { }, complete: function () { chat_area.find(".loader").remove(); chat_box.find(".btn-chat").prop("disabled", true); chat_box.find(".chat_input").val(""); chat_area.animate({scrollTop: chat_area.offset().top + chat_area.outerHeight(true)}, 800, 'swing'); } }); } /** * This function called by the send event triggered from pusher to display the message * * @param message */ function displayMessage(message) { let alert_sound = document.getElementById("chat-alert-sound"); if($("#current_user").val() == message.from_user_id) { let messageLine = getMessageSenderHtml(message); $("#chat_box_" + message.to_user_id).find(".chat-area").append(messageLine); } else if($("#current_user").val() == message.to_user_id) { alert_sound.play(); // for the receiver user check if the chat box is already opened otherwise open it cloneChatBox(message.from_user_id, message.fromUserName, function () { let chatBox = $("#chat_box_" + message.from_user_id); if(!chatBox.hasClass("chat-opened")) { chatBox.addClass("chat-opened").slideDown("fast"); loadLatestMessages(chatBox, message.from_user_id); chatBox.find(".chat-area").animate({scrollTop: chatBox.find(".chat-area").offset().top + chatBox.find(".chat-area").outerHeight(true)}, 800, 'swing'); } else { let messageLine = getMessageReceiverHtml(message); // append the message for the receiver user $("#chat_box_" + message.from_user_id).find(".chat-area").append(messageLine); } }); } }
As shown in the code when we click the send btn it will call the send function to make an ajax request to the server, after that comes the magic in this line:
// listen for the send event, this event will be triggered on click the send btn channel.bind('send', function(data) { displayMessage(data.data); });
This code listens for the send event that we already subscribed it in the server previously so every time you send a message to server the server fires an event which in turn get caught in the javascript code, and get displayed using displayMessage() function.
Handling old messages on scroll up:
If we need to fetch the old messages on scrolling up like facebook we can accomplish that using the first message created date so
open app/Http/Controllers/MessagesController.php and add this method:
/** * getOldMessages * * we will fetch the old messages using the last sent id from the request * by querying the created at date * * @param Request $request */ public function getOldMessages(Request $request) { if(!$request->old_message_id || !$request->to_user) return; $message = Message::find($request->old_message_id); $lastMessages = Message::where(function($query) use ($request, $message) { $query->where('from_user', Auth::user()->id) ->where('to_user', $request->to_user) ->where('created_at', '<', $message->created_at); }) ->orWhere(function ($query) use ($request, $message) { $query->where('from_user', $request->to_user) ->where('to_user', Auth::user()->id) ->where('created_at', '<', $message->created_at); }) ->orderBy('created_at', 'ASC')->limit(10)->get(); $return = []; if($lastMessages->count() > 0) { foreach ($lastMessages as $message) { $return[] = view('message-line')->with('message', $message)->render(); } PusherFactory::make()->trigger('chat', 'oldMsgs', ['to_user' => $request->to_user, 'data' => $return]); } return response()->json(['state' => 1, 'data' => $return]); }
Yet a gain we fired a new event called ‘oldMsgs‘.
Now update routes/web.php:
<?php Route::get('/', 'HomeController@index'); Route::get('/load-latest-messages', 'MessagesController@getLoadLatestMessages'); Route::post('/send', 'MessagesController@postSendMessage'); Route::get('/fetch-old-messages', 'MessagesController@getOldMessages'); Auth::routes();
Then open public/js/chat.js and update it as follows:
$(function () { .... // handle the scroll top of any chat box // the idea is to load the last messages by date depending of last message // that's already loaded on the chat box let lastScrollTop = 0; $(".chat-area").on("scroll", function (e) { let st = $(this).scrollTop(); if(st < lastScrollTop) { fetchOldMessages($(this).parents(".chat-opened").find("#to_user_id").val(), $(this).find(".msg_container:first-child").attr("data-message-id")); } lastScrollTop = st; }); // listen for the oldMsgs event, this event will be triggered on scroll top channel.bind('oldMsgs', function(data) { displayOldMessages(data); }); }); /** * fetchOldMessages * * this function load the old messages if scroll up triggerd * * @param to_user * @param old_message_id */ function fetchOldMessages(to_user, old_message_id) { let chat_box = $("#chat_box_" + to_user); let chat_area = chat_box.find(".chat-area"); $.ajax({ url: base_url + "/fetch-old-messages", data: {to_user: to_user, old_message_id: old_message_id, _token: $("meta[name='csrf-token']").attr("content")}, method: "GET", dataType: "json", beforeSend: function () { if(chat_area.find(".loader").length == 0) { chat_area.prepend(loaderHtml()); } }, success: function (response) { }, complete: function () { chat_area.find(".loader").remove(); } }); } function displayOldMessages(data) { if(data.data.length > 0) { data.data.map(function (val, index) { $("#chat_box_" + data.to_user).find(".chat-area").prepend(val); }); } }
As shown in the code above i listened for scroll event then i added a condition to check if we scroll in the up direction not down then we called function fetchOldMessages() which in return will fire an event to the server.
Download the source code for Laravel 8
Thank you for such an awesome tutorial. Really helpful! But I encountered some issues while using it, this might help the next user. 1. In Chat.Js line 67. ${message.fromUserName} is not defined. I Solved this by passing it from the controller, with this code $message->fromUserName = $message->owner->fname; 2. The messages appear in ascending order when displayed. I put the message in an array and reversed the order. Here is the code in MessageController for getLoadLatestMessages, $messages = Message::where(*****)->orderBy(‘created_at’, ‘DESC’)->limit(10)->with(‘owner’)->get(); $messagereturn = []; foreach ($messages as $message) { $messagereturn[] = view(‘message-line’)->with(‘message’, $message)->render(); } $newmessage = array_reverse($messagereturn); // necessary 3. When getting… Read more »
Excelente amigo busque por todo lados y no encontraba un tutorial tan claro como este muchas gracias
Gracias
after send message chat line not added in chat area.please help.
PusherFactory::make()->trigger(‘chat’, ‘send’, [‘data’ => $message]); this is the issue . nothing triggred
Be sure that you set up the pusher configuration correctly as described in the tutorial, sometimes you need to clear laravel cache and config so that laravel can read configurations from .env
getting error 505 internal serval error after sending a message and can’t get sent messages
What is the error saying?
internal server error, that’s what is displayed at the console
Rectified, did not put the files in the right directory
Please Help me,
When this application browser run then registration when submit then below the message. but not login access. why?
It means you should have users to chat with
Uncaught ReferenceError: channel is not defined
at HTMLDocument.<anonymous> (chat.js:22)
at c (jquery.min.js:3)
at Object.fireWith [as resolveWith] (jquery.min.js:3)
at Function.ready (jquery.min.js:3)
at HTMLDocument.H (jquery.min.js:3)
i got this error
It seems that you didn’t include the pusher javascript sdk
how to add pusher javascript sdk
As mentioned in the article
<script src="https://js.pusher.com/4.1/pusher.min.js"></script>
Still not working. Can you help me ?
chat.js:191 Uncaught ReferenceError: channel is not defined
at HTMLDocument.<anonymous> (chat.js:191)
at j (jquery-1.11.1.min.js:2)
at Object.fireWith [as resolveWith] (jquery-1.11.1.min.js:2)
at Function.ready (jquery-1.11.1.min.js:2)
at HTMLDocument.J (jquery-1.11.1.min.js:2)
Were you able to solve it ? I am getting same error. Can Anyone Help me ?
Hi, the chat is working fine at both ends. But, it is not working in real-time. It requires to close the chat panel and re-open to get the latest message. Similarly, at the sender end after sending the message, it requires to close the chat and re-open to see the sent message. Any help to resolve the issue would be appreciated.
Looks like pusher is not working with you, just check the pusher configuration and turn on debug mode for pusher messages
Hi Wael,
Thank you very much for your response. Yeah, there was some issue with the Pusher configuration. Now, it is working in real-time.
Could it be that the messages I sent are not visible and not communicating due to the pusher event or channel?
Check the pusher dashboard and see the logs to check if the message is already sent,
Note also that this tutorial is intended for laravel 5.5 and may be not compatible with higher versions
so i will try to make another tutorial for laravel 8 in the future.
hi,after send the message the message line didnot add in chat box ,why ?
Check your pusher configuration is correct, there is a a flag to debug the message sending
Pusher.logToConsole = true;
I followed all the steps but when I write a message it does not appear automatically in the chat window, when I close the chat and reopen it if it appears and does not show me any error, what could it be?
You have something wrong with pusher config check that pusher is working properly using the pusher dashboard
hello, I’m getting undefine message in chat box. messages are being set real time. both users get messages but I want to refresh the page to see the real message till then it displays “undefine“
undefined means something wrong in javascript code
It’s work. But I can’t attach file into message.
I think to attach a file you have to update the database to add another column to save the media files and you need to update the chat box to include a button to select a file to upload and send it in the same way as sending the text message
Can anyone solve this error ? I have done excat code given. Still gettting this error. I have even installed pusher by composer.
chat.js:191 Uncaught ReferenceError: channel is not defined
at HTMLDocument.<anonymous> (chat.js:191)
at j (jquery-1.11.1.min.js:2)
at Object.fireWith [as resolveWith] (jquery-1.11.1.min.js:2)
at Function.ready (jquery-1.11.1.min.js:2)
at HTMLDocument.J (jquery-1.11.1.min.js:2)
I don’t know that you missing something, but here are the steps: – Note that this project is compatible with laravel 5.5 – Download the source code from this link http://webmobtuts.com/wp-content/uploads/code/chat.zip – Extract the archive and move it into your server directory for example in linux /var/www/html – cd into the project folder and run composer install – configure the .env file and create the file if not exists (update the db settings and pusher settings) – run these commands to clear the cache: php artisan cache:clear php artisan config:clear php artisan config:cache – migrate the db with this command:… Read more »
very helfull.. i tried in laravel 8.3 working find.. but have to fixed Message.php because your tutorial didn’t mention this
public function fromUser()
{
return $this->belongsTo(‘App\User’, ‘from_user’);
}
public function toUser()
{
return $this->belongsTo(‘App\User’, ‘to_user’);
}
Note that the pusher SDK have changed a lot since laravel 5.5
When sending the message i got this error
“message”: “Class ‘Pusher\\Pusher’ not found”,
“exception”: “Symfony\\Component\\Debug\\Exception\\FatalThrowableError”,
“file”: “/home/stscrm/public_html/STScrmApp/crmChat/app/Lib/PusherFactory.php”,
“line”: 13,
What laravel version do you use?
– This tutorial compatible with laravel 5.5
– If your laravel version be sure that you install pusher
– Be sure to run
composer dump-autoload
thank you
Hi, how do I set up a way to determine if user online or not
I don’t have an idea for this right now but there is an article on Pusher website for this scenario using laravel Echo
https://pusher.com/tutorials/online-presence-laravel/
I followed the steps above in my project and it worked fine on my local machine.
When I uploaded the code on the server, it first run fine but after sending 10-12 messages, it stopped working and it’s giving an error,
“Argument 1 passed to Pusher\\Pusher::__construct() must be of the type string, null given”
Strange, it’s supposed that the pusher free plan allows sending more than 200000 messages per day.
https://pusher.com/channels/pricing
Any Source Code available
The source code at the bottom of the article
Hello brother, who ever you are, you are a legend, now following the bull shit tech stack and sticking to simplicity, thank you.
Thanks
Hello sir, do u use vue js for laravel8. Thanks
No, this tutorial with laravel only.
Right now i am preparing a simple tutorial with laravel 8 and vue 3 but it will be completed after 3 weeks to 1 month
Thanks. But you provide souce code for laravel 8. and that one is only laravel 8 or vue and laravel.
Hello sir i have download and install laravel 8 source code. Its work but not for realtime.
In console gives error
[Vue warn]: Cannot find element: #app
please help how to solve
This error comes from the Vue instance, by the way i am not using vue in this app so you can open resources/js/app.js and comment this block:
/*const app = new Vue({
el: ‘#app’,
});*/
and open layouts/app2.blade.php and make sure there is only one script tag
Also move this script to the bottom
I have updated the repo you can download it again
Thanks. successfully run this project. But When I apply this one of my existing project receiver message does not appear real time. but in pusher messages are counting.
For real time issues check your existing pusher version, i encountered the realtime problem before and it seems that pusher versions usually make problems when submitting messages.
bro how to solve this error
chat.js:20 Uncaught ReferenceError: channel is not defined
at HTMLDocument.<anonymous> (chat.js:20:5)
at j (jquery-1.11.1.min.js:2:27244)
at Object.fireWith [as resolveWith] (jquery-1.11.1.min.js:2:28057)
at Function.ready (jquery-1.11.1.min.js:2:29891)
at HTMLDocument.J (jquery-1.11.1.min.js:2:30257)
Strange i don’t see this error before, download the working repository instead
Is it real time chat?
Yes pusher is realtime
Hello,
I am trying to configure this chat app into my system. I found an error “Uncaught You must pass your app key when you instantiate Pusher”.
How to set this error in bugs
You have to create a pusher account through https://pusher.com and create a new app and get the app key, then use it in laravel project as i describe in the tutorial
message will receive after page refresh.
can you help me?
i just clone your project.
add pusher key as well.
No it should be received immediatly, most of the time the reason of this problem is that pusher is not working. Check that pusher is working and received the message through pusher dashboard
Hi, i have been following you tutorials and they are really great.
Currently i am trying to add the chat functionality in the CRM tutorial you created ealier.
I have done it twice.
First i did the aplication as per your tutorial(the chat app with pusher).
Then i decided to add it in the crm.
But now it is not working.I get this error in the PusherFactory.php(shown in the screenshort)
kindly can you help me out to see how i can add the chat in the crm
Did you installed Pusher? Also check the Pusher version used in this tutorial.
yes i installed pusher using the following command
Try to download the tutorial and run it first before integrating in your app
I downloaded the tutorial,its working perfectly.
How do i now integrate this in my project?for example the CRM tutorial.
do i follow the same project structure in this “chat tutorial” or i embrace the structure of the “mini-crm”?
Yes if you understand the tutorial just make the sample db tables and copy the code to match your needs, i think this is not difficult