How to build a simple chat app with Laravel, Vue and pusher

What is Laravel Echo

First of all.. what is Laravel Echo?
Laravel Echo is a Javascript library that makes it painless to subscribe to channels and listen for events broadcast by Laravel.

Dependencies you have to install

First of all, you need to install these packages to get up and running with Laravel Echo / Broadcasting events.
You may install Echo via the NPM package manager. In this example, we will also install the pusher-js package since we will be using the Pusher broadcaster:
So you can run npm install --save laravel-echo pusher-js in your terminal.

If you are broadcasting your events over Pusher, you should install the Pusher PHP SDK using the Composer package manager:
composer require pusher/pusher-PHP-server

Backend setup

Now when you have all the dependencies installed, it's time to setup a pusher.com account. When you have created an account and created an App you should see some App keys under the tab App keys.
Copy that keys to your .env file like this

PUSHER_APP_ID=23222  
PUSHER_KEY=ffssfb166f4976941e627c5  
PUSHER_SECRET=2o2323ojfw  

And remember to se the broadcast driver so Laravel knows what driver you want to use

BROADCAST_DRIVER=pusher  

In your config/broadcasting.php file, it's a good idea to add some options to your pusher connection like this

'pusher' => [  
            'driver' => 'pusher',
            'key' => env('PUSHER_KEY'),
            'secret' => env('PUSHER_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => 'eu',
                'encrypted' => true
            ],
        ],

I was having some trouble to find out why my connection didn't work, and that was because of the missing options.

Now we should create an event to see if we can push some message to our Pusher account.

Go to your terminal and type php artisan make event ChatMessageWasReceived

find the class in your app/events/ChatMessageWasReceived.php and it should implement the ShouldBroadcast . so like this

class ChatMessageWasReceived implements ShouldBroadcast  
{

Now we want to create a model for our chat messages, do that by typing
php artisan make:model ChatMessage --migration That will create a model and a migration for us, just start with this or add your own rows.

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

Remember to add $fillable to the model.

class ChatMessage extends Model  
{
    public $fillable = ['user_id', 'message'];
}

Now let's inject a user and our messages to our Event

class ChatMessageWasReceived implements ShouldBroadcast  
{
    use InteractsWithSockets, SerializesModels;

    public $chatMessage;
    public $user;

    /**
     * Create a new event instance.
     *
     * @param $chatMessage
     * @param $user
     */
    public function __construct($chatMessage, $user)
    {
        $this->chatMessage = $chatMessage;
        $this->user = $user;
    }

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

In our route file web.php file we will set up a route for our Javascript to make an ajax call to with a message.

// Send a message by Javascript.
Route::post('message', function(Request $request) {

    $user = Auth::user();

    $message = ChatMessage::create([
        'user_id' => $user->id,
        'message' => $request->input('message')
    ]);

    event(new ChatMessageWasReceived($message, $user));


});

We grab the logged in user to insert the id and the message in the chat_messages table.
and fire of the event with the message and the user object.

And that's it for the backend.

frontend setup

Laravel 5.3 ships with some javascript files that setup jquery, bootstrap, vue and vue-resource that is really handy to get up and running fast.
Now we need to import Laravel Echo's frontend library, do that by going to resources/assets/js/bootstrap.js at the bottom you see some code that is commented out, uncomment that so you have this:

import Echo from "laravel-echo"

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

Remember to add your own pusher key.
Tip Again you might add options for cluster and encrypted.

Next, go and create a file named chat.js and put it into the javascript components folder and add this code

module.exports = {

    data() {
        return {
            posts: [],
            newMsg: '',

        }
    },


    ready() {
        Echo.channel('public-test-channel')
            .listen('ChatMessageWasReceived', (data) => {

                // Push ata to posts list.
                this.posts.push({
                    message: data.chatMessage.message,
                    username: data.user.name
                });
            });
    },

    methods: {

        press() {

            // Send message to backend.
            this.$http.post('/message/', {message: this.newMsg})
                .then((response) => {

                    // Clear input field.
                    this.newMsg = '';
                });
        }
    }
};

First of all in the ready() method it will listen for the channel public-test-channel that we specified in the Event ChatMessageWasReceived
Next it will listen for any events that comes to the Event class and then it will push the recived data into the posts data array.

The press() method will send an ajax request to our route file with the message typed in by the user in our view (we haven't created that yet)

Last we need to add our component to the app.js file like this

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

Setup the view file

The last thing we need to add is an input field for our user to start chatting.
I think it's a good place to add that in the home.blade.php file that ships with Laravel by default.
You can find the file in resources/views/home.blade.php
Now we will add an inline-template that is created by Vue and use our new Vue component we just created.
Go ahead and add this

<div class="panel-body">  
    <chat inline-template>

    You are logged in!

    <hr>

    <h2>Write something to all users</h2>
    <input type="text" class="form-control" placeholder="something" required="required" v-model="newMsg" @keyup.enter="press">

    <hr>
    <h3>Messages</h3>

    <ul v-for="post in posts">
    <b>@{{ post.username }} says:</b> @{{ post.message }}</li>
    </ul>

    </chat>
</div><!-- panel-body -->  

We add a input field with v-model="newMsg" and a @keyup.enter="press" to trigger our Vue method when the user press Enter.

In the <ul> we just loop through all the user's posts.

Wrapping up

So that's how you can create a simple chat app with Laravel 5.3 and Vue.
go ahead and open 2 browsers and see if your chat is working.
If you have any issues try running gulp in your terminal.