Search code examples
node.jslaravelvue.jspusherlaravel-echo

Laravel Echo listener is not listening


this is my first project with vue and nodejs so please let me know if I there is a missing information. I'm trying to develop a group chat with Laravel, Vue js and Pusher.

Database Tables and Relations

I want to create a private Channel for each team which is available. As soon as you click on the group chat, the existing messages get loaded and shown. When you send a message, the message gets added to the messages table and is also sent successfully to pusher as you can see here: Pusher message

The message is also added to the message list on the sender but not on the other team members.

Sender

Other team members

The new message is only shown on the other team members when they reload the page. That means that the echo listener doesn't seem to work. What can I do to fix it? What is wrong?

Here is my code:

ChatApp.vue (root component)

<template>
<div class="chat-container row">
    <i class="far fa-comments fa-3x"></i>
    <div id="chat-app" class="chat-app">
        <div class="row mx-0 h-100 overflow-hidden">
            <TeamList :teams="teamList" @selected="startConversationWith"/>
            <Conversation :team="selectedTeam" :messages="messages" @new="saveNewMessage"/>
        </div>
    </div>
</div>
</template>

<script>
import MessageList from './MessageList';
import TeamList from './TeamList';
import Conversation from './Conversation';
import MessageTextBox from './MessageTextBox';

export default {
    props: {
        user: {
            type: Object,
            required: true
        }
    },
    data() {
        return {
            messages: [],
            teamList: [],
            selectedTeam: null,
        }
    },
    mounted() {
        Echo.private('messages.1')
            .listen('NewMessage', (e) => {
                this.handleIncoming(e.message);
            });

        axios.get('/teams')
            .then((response) => {
                this.teamList = response.data;
            });
    },
    methods: {
        startConversationWith(team) {
            axios.get('/conversation/' + team.id)
                .then((response) => {
                    this.messages = response.data;
                    this.selectedTeam = team;
                });
        },
        saveNewMessage(text) {
            this.messages.push(text);
        },
        handleIncoming(message) {
            this.saveNewMessage(message);
            return;
        }
    },
    components: {TeamList, MessageList, MessageTextBox, Conversation}
}
</script>

App/Events/NewMessage.php

<?php

namespace App\Events;

use App\Message;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class NewMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;

public $message;

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

/**
 * Get the channels the event should broadcast on.
 *
 * @return \Illuminate\Broadcasting\Channel|array
 */
public function broadcastOn()
{
    return new PrivateChannel('messages.' . $this->message->team_id);
}

public function broadcastWith()
{
    $this->message->load('team');
    return ["message" => $this->message];
}
}

routes/channels.php

use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('messages.{id}', function ($team_id, $message) {
return true;
//    return (int) $team->id === (int) $id;
});

Message model

namespace App;
use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
protected $guarded = [];

public function team()
{
    return $this->belongsTo('App\Team');
}

public function user()
{
    return $this->belongsTo('App\User');
}
}

ContactsController

namespace App\Http\Controllers;

use App\Events\NewMessage;
use App\Message;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;

class ContactsController extends Controller
{

public function getTeams() {
    $teams = Auth::user()->teams;
    return response()->json($teams);
}


public function getMessagesFor($id)
{
    $messages = Message::where('team_id', $id)->get();
    return response()->json($messages);
}

public function send(Request $request) {
    $message = Message::create([
        'team_id' => $request->team_id,
        'user_id' => Auth::user()->id,
        'message' => $request->text
    ]);
    broadcast(new NewMessage($message));
    return response()->json($message);
}
}

bootstrap.js

window._ = require('lodash');

/**
 * We'll load jQuery and the Bootstrap jQuery plugin which provides support
 * for JavaScript based Bootstrap features such as modals and tabs. This
 * code may be modified to fit the specific needs of your application.
*/

try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');

require('bootstrap');
} catch (e) {}

/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
*/

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

/**
 * Echo exposes an expressive API for subscribing to channels and listening
 * for events that are broadcast by Laravel. Echo and event broadcasting
 * allows your team to easily build robust real-time web applications.
*/

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
});

Solution

  • encrypted is set to true for SSL config. Try setting it to false when configuring laravel echo in bootstrap.js