Я использовал 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
но мне не повезло.
Мне наконец удалось это выяснить. Я просмотрел файлы 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 в функции обратного вызова из проверки auth, которую выполняет файл 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'
});
Других решений пока нет …