Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

bwrigley's avatar

Echo processing twice after Intertia Logout/Login

Hi,

Just trying Laravel Echo/Pusher for the first time in my Vue application and I'm getting some strange behaviour with each event triggering twice.

But it only happens when I logout and log back in again and only if I logout via an Inertia method (via Link or form helper):

Logging out with this causes double-counting next time I login:

<Link href="/logout" method="get" as="button" type="button">Inertia Logout</Link>

This doesn't cause a problem:

<a href="/logout">HTML Logout</a>

My first thought was that the wasn't closing the channel correctly when I logout via an Inertia link, but If that were the case I would expect Pusher to log 3 messages (1 for input message and 1 back out to each open channel right?), but it only logs 2.

Any thoughts on what might be going on here?

In case these are helpful:

bootstrap.js:

import Echo from 'laravel-echo';

import Pusher from 'pusher-js';
window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
    //wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
    //wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
    //wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
    forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
    //enabledTransports: ['ws', 'wss'],
});

channels.php:

Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
    return (int) $user->id === (int) $id;
});

Vue component

<script setup>

import { onMounted } from 'vue';
import {  usePage, Link  } from '@inertiajs/vue3';

defineProps({
    posts: {
        type: Array,
    }

});


const page = usePage();


onMounted(() => {

    console.log('onMounted is triggerd' +  crypto.randomUUID());

    //listener for broadcast events via pusher and echo
    Echo.private('App.Models.User.' + page.props.auth.user.id)
        .notification((notification) =>{
            //router.reload({ only: ['auth'] });

            console.log(notification.id + " " + crypto.randomUUID() );

            switch(notification.type) {
                case 'App\Notifications\NewMention':
                    console.log('calling ' + notification.id );
                    page.props.auth.unreadNotificationsCount++;
                    break;
            }
    });
});

</script>

<template>

    Test {{  $page.props.auth.unreadNotificationsCount }}

    <Link href="/logout" method="get" as="button" type="button">Inertia Logout</Link>
    <a href="/logout">HTML Logout</a>

</template>

Notification :

<?php

namespace App\Notifications;

use App\Models\Comment;
use App\Models\Post;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class NewMention extends Notification implements ShouldQueue
{
    use Queueable;

    protected $postable;

    /**
     * Create a new notification instance.
     */
    public function __construct(Post|Comment $postable)
    {
        $this->postable = $postable;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @return array<int, string>
     */
    public function via(object $notifiable): array
    {
        return ['database','broadcast'];
    }

    /**
     * Get the mail representation of the notification.
     */
    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
                    ->greeting('Hi!')
                    ->line('You have been mentioned in a post!.')
                    ->action('View Notifications', url('/notifications'));
    }

    /**
     * Get the array representation of the notification.
     *
     * @return array<string, mixed>
     */
    public function toArray(object $notifiable): array
    {
        return [
            'user' => $this->postable->user->only(['username','avatar']),
            'postable' => $this->postable->only(['id'])
        ];
    }

    /**
     * Get the array representation of the notification.
     *
     * @return array<string, mixed>
     */
    public function toBroadcast(object $notifiable): array
    {
        return [];
    }
}
0 likes
0 replies

Please or to participate in this conversation.