Laravel Echo не будет ловить события с socket.io

Я использовал Redis с Socket.io для установки обновлений в реальном времени, но Laravel Echo не ловит события.

Если я использую экземпляр io(), он работает просто отлично. Вот мой код в моем приложении Vue для прослушивания событий:

НЕ будет ловить события

window.Echo.channel('users')
    .listen('UserCreated', event => {
            console.log(event);
            this.all_users.push(event.user);
            this.filter_data();
    });

Будет ловить события

window.socket = io(window.location.origin+':3000');
window.socket.on('users:App\\Events\\UserCreated', function(data){
    console.log(data);
    console.log('from socket');
    this.all_users.push(data.user);
    this.filter_data();
}.bind(this));

Мой узел js код для отправки событий.

var server = require('http').Server();

var io = require('socket.io')(server);

var Redis = require('ioredis');

var redis = new Redis();

redis.subscribe('users', function(error, count){
    console.log(error);
    console.log(count);
});

redis.on('message', function(channel, message){
    console.log(channel);
    message = JSON.parse(message);
    console.log(message);
    const emmitChannel = `${channel}:${message.event}`;
    console.log(emmitChannel);
    io.emit(emmitChannel, message.data);
});

server.listen(3000);

Моя трансляция событий Laravel

<?php

namespace App\Events;

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


//Models
use App\User;

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

    public $user;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;

        $this->dontBroadcastToCurrentUser();
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return ['users'];
    }
}

Я попытался изменить способ передачи событий в Laravel Echo, так как по умолчанию он получает их как users:App\Events\UserCreated но мне не повезло.

1 ответ

Решение

Мне наконец удалось это выяснить. Я просмотрел файлы JS и сумел связать его с тем фактом, что код в этой строке имеет try catch section на самом деле не выдает ошибок, если проверка Laravel channel.php на то, кто может прослушивать канал, не возвращает экземпляр пользовательской модели, как должно.

Нечто подобное в Channels.php выдает эту ошибку:

Broadcast::channel('users', function ($user) {
    if($user->type == 'admin'){
         return $user;
    }else{
         return false;
    }
});

Если $user не проходит if проверить Laravel вернется false, Так как он не возвращает JSON и просто ложь, я думаю, что это должно регистрировать, что тело ответа не прошло JSON.parse() функция, чтобы вы могли видеть это в терминале. Что-то вроде этого:

try {
     body = JSON.parse(response.body);
} catch (e) {
     Log.warning('Response body provided is not expected JSON. Response body provided ${response.body}');
     body = response.body;
}

Таким образом, мы можем видеть, не возвращает ли Laravel экземпляр пользовательской модели.

Поэтому, когда вы не получаете ожидаемый экземпляр пользовательской модели, не существует пользовательского объекта для кода, к которому нужно присоединить sockedId, потому что он не определен. Никогда не было JSON для создания объекта.

Я думаю, что код должен перестать пытаться подключиться к каналу присутствия или частному каналу, если вы не получите экземпляр пользователя, вместо того, чтобы пытаться присоединить идентификатор сокета.

В любом случае, чтобы действительно вернуть пользователя, убедитесь, что вы вошли в систему, используя систему аутентификации Laravel. Если вы не использовали это, возможно, вам придется поработать, чтобы заставить его работать. Если вы не используете его, то эта функция в Laravel выдаст ошибку 403, потому что она не может найти вас, чтобы войти в систему.

Мне пришлось переписать функцию, которая проверяет алгоритм хеширования пароля, в пользовательский алгоритм с провайдером, чтобы я не связывался с ядром Laravel и заставлял пользовательскую модель расширять класс, который ищет Laravel.

Затем в своем файле channel.php просто убедитесь, что при проверке вы действительно возвращаете $ user в функции обратного вызова из проверки подлинности, которую выполняет файл Broadcaster.php. Что-то вроде этого:

Broadcast::channel('users', function ($user) {
     return $user;
});

Это очень простой частный канал / канал присутствия, но с вошедшим в систему пользователем и возвратом $ user, эта ошибка не исчезнет.

Также убедитесь, что вы вызываете socket.io в своем экземпляре Echo следующим образом:

window.Echo = new Echo({
    broadcaster:  'socket.io',
    host: window.location.origin + ':6001'
});
Другие вопросы по тегам