开发者问题收集

私人频道无法与 Laravel 回显服务器配合使用

2017-04-10
14626

我在控制台上收到此 JS 错误:

app.js:167 Uncaught ReferenceError:receiverId 未定义

这是我的完整代码:

PrivateChatController:

event(new PrivateMessageEvent($chat, $receiverId));

PrivateMessageEvent:

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;
use App\User;
use App\PrivateChat;

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

    public $privateChat, $receiverId;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(PrivateChat $privateChat, $receiverId)
    {
        $this->privateChat = $privateChat;
        $this->receiverId = $receiverId;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('private-chat.' . $this->receiverId);
    }
}

Bootstrap.js

import Echo from "laravel-echo"

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001'
});

window.Echo.private(`private-chat.${receiverId}`)
    .listen('PrivateMessageEvent', (e) => {
        console.log(e);
});

channels.php

Broadcast::channel('private-chat.{receiverId}', function ($user, $receiverId) {
    return true; // this is just for debugging to allow anyone to listen on this channel
    //return $user->id === $receiverId;
});

laravel-echo-server.json

{
    "authHost": "http://localhost",
    "authEndpoint": "/broadcasting/auth",
    "clients": [],
    "database": "redis",
    "databaseConfig": {
        "redis": {},
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": true,
    "host": null,
    "port": "6001",
    "protocol": "http",
    "socketio": {},
    "sslCertPath": "",
    "sslKeyPath": ""
}

在后台 queue:work laravel-echo-server 已在运行

触发该事件,我在 laravel-echo-server 控制台上收到此消息:

Channel: private-private-chat.
Event: App\Events\PrivateMessageEvent
CHANNEL private-private-chat.

注意:

我花了 10 多个小时,尝试了所有能尝试的方法,但还是没有成功。

谢谢

3个回答

您可以将 REDIS_PREFIX 设置为 NULL 以删除前缀,否则如果它有值,那么您必须在 echo 服务器配置中设置 keyPrefix

If REDIS_PREFIX = NULL then do not add keyPrefix .


Important Notice

When using broadcastAs() , the call to listen('') call must start with a DOT

At this moment the behavior when keyPrefix is used is unknown, if you use the prefix settings, please comment on the outcome of the DOT requirement.

https://laravel.com/docs/6.x/broadcasting#broadcast-name

public function broadcastAs()
{
    return 'server.created';
}
.listen('.server.created', function (e) {
    ....
});
28675576​​9

If you do not use broadcastAs() then the naming will fallback to the event class name, in this case there is no DOT prefix injected, see the setup below:

laravel-echo-server.json

{
    "host": "127.0.0.1",
    "port": "6001",
    "protocol": "http",

    "database": "redis",

    "databaseConfig": {
        "redis": {
            "host": "127.0.0.1",
            "port": 6379,
            "db": 0,
            "keyPrefix": "VALUE OF REDIS_PREFIX"
        }
}

/app/Events/MyExample.php

<?php

namespace App\Events;

use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

class MyExample implements ShouldBroadcastNow
{

  private $id;

  public $payload;

  public function __construct($id, $payload)
  {
    $this->id = $id;
    $this->payload = $payload;
  }

  public function broadcastOn()
  {
    return new PrivateChannel('example.' . $this->id);
  }

}

触发事件(PHP)

use App\Events\MyExample

$payload = [
 'duck' => 'sauce',
 'Bass' => 'Epic'
];

event(new MyExample($id, $payload))

监听事件(JavaScript)

Echo.private(`example.${id}`).listen('MyExample', event => {

  console.log('payload', event.payload)

})
Marc
2020-04-02

尝试将此行:

$this->$receiverId = $receiverId;

更改为此行:

$this->receiverId = $receiverId;

在您的 PrivateMessageEvent __construct() 中

更新:

尝试使用像这样的固定频道 ID:

window.Echo.private('private-chat.1')

我建议您也使用存在频道,它也是私人的,但具有更多功能,即:

Echo.join('private-chat.1')
   .listen('PrivateMessageEvent', (e) => {
    console.log(e);
});

如果您使用像您使用的动态频道号,即:

window.Echo.private(`private-chat.${receiverId}`)

您必须在 javascript 中为 receiverId 一个值,这个声明是一个通用的房间监听器,但应该定义receiverId,${receiverId} 是一个字符串插值。

您可以定义在包含 app.js 之前在模板中指定receiverId,例如使用 blade 语法:

<script>
   receiverId = {{ $receiverId }};
</script>

另一个想法:我想明确的是,在上面所有的代码中,receiverId 代表客户端想要加入的聊天室/房间的id,而不是接收用户的id。

dparoli
2017-04-10

尝试使用 event(new PrivateMessageEvent($chat, $receiverId)); 这个

App\Events\PrivateMessageEvent::dispatch($chat, $receiverId);
Gor Azizyan
2018-11-06