我正在尝试使用Laravel和ReactJS和Pusher创建一个实时帖子。我已经能够创建推送事件,并且可以在推送站点上看到事件。但是,Laravel echo在创建事件时就不会监听该事件,而且我无法弄清楚为什么或如何使其监听。
App \ Events \ PostCreated
<?php
namespace App\Events;
use App\Post;
use App\User;
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;
class PostCreated implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $post;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Post $post, User $user)
{
//
$this->post = $post;
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return [
new PrivateChannel('new-post'),
new PrivateChannel('App.User.' . $this->post->user->id),
];
}
/**
* @return array
*/
public function broadcastWith() {
return [
'post' => array_merge($this->post->toArray(), [
'user' => $this->post->user,
]),
'user' => $this->user,
];
}
}
broadcasting.php
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => getenv('PUSHER_APP_KEY'),
'secret' => getenv('PUSHER_APP_SECRET'),
'app_id' => getenv('PUSHER_APP_ID'),
'options' => [
'cluster' => getenv('PUSHER_APP_CLUSTER'),
'encrypted' => true,
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
.env
BROADCAST_DRIVER=pusher
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
PUSHER_APP_ID=757605
PUSHER_APP_KEY=4100ca8b118192fd01b2
PUSHER_APP_SECRET=41f43d23204a3c7ae2a7
PUSHER_APP_CLUSTER=ap1
bootstrap.js
/**
* 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');
//const client = require('pusher-js');
//import 'pusher-js/node';
window.Echo = new Echo({
broadcaster: 'pusher',
key: '4100ca8b118192fd01b2',
cluster: 'ap1',
encrypted: true
});
channels.php
<?php
/*
|--------------------------------------------------------------------------
| Broadcast Channels
|--------------------------------------------------------------------------
|
| Here you may register all of the event broadcasting channels that your
| application supports. The given channel authorization callbacks are
| used to check if an authenticated user can listen to the channel.
|
*/
use Illuminate\Support\Facades\Auth;
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('new-post', function ($user) {
return Auth::check();
});
PostController
public function create(Request $request, Post $post) {
$data = [];
$video_data = [];
if ($request->get('file')) {
foreach ($request->get('file') as $file) {
$name = md5(uniqid()) . '.' . explode('/', explode(':', substr($file, 0, strpos($file, ';')))[1])[1];
$upload = Uploader::upload($file, array('public_id' => $name));
array_push($data, $upload['secure_url']);
}
}
if ($request->get('video')) {
foreach ($request->get('video') as $file) {
$name = md5(uniqid() . '.' . explode('/', explode(':', substr($file, 0, strpos($file, ';')))[1]))[1];
$upload = Uploader::upload($file, array('public_id' => $name, 'resource_type' => 'video'));
array_push($video_data, $upload['secure_url']);
}
}
$image = !empty($data) ? json_encode($data) : null;
$video = !empty($video_data) ? json_encode($video_data) : null;
$body = $this->test_data($request->body);
// create post
$createdPost = $request->user()->posts()->create([
'body' => $body,
'image' => $image,
'video' => $video
]);
// broadcast
broadcast(new PostCreated($createdPost, $request->user()))->toOthers();
// return the response
return response()->json($post->with('user')->find($createdPost->id));
}
app.blade.php(应用布局)
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
'user' => [
'id' => Auth::check() ? Auth::user()->id : null,
'following' => Auth::check() ? Auth::user()->following()->pluck('users.id') : null
],
]);
?>
</script>
ReactJS(前端)
componentDidMount() {
Echo.private('new-post').listen('PostCreated', (e) => {
if (window.Laravel.user.following.includes(e.post.user_id)) {
this.setState({ posts: [e.post, ...this.state.posts] });
}
});
// this.interval = setInterval(()=>this.getPosts(), 10000);
}
我希望创建新帖子的用户的关注者可以立即看到该帖子,而无需重新加载页面,但是什么也没有发生。
事件已创建,但未监听。我在做什么错了?
答案 0 :(得分:0)
尝试在事件类中设置broadcastAs
,并在reactjs部分中显式设置广播名称。
App \ Events \ PostCreated
<?php
namespace App\Events;
class PostCreated implements ShouldBroadcast
{
// other code
public function broadcastAs()
{
return 'PostCreated';
}
}
ReactJS(前端)
componentDidMount() {
Echo.private('new-post').listen('.PostCreated', (e) => {
if (window.Laravel.user.following.includes(e.post.user_id)) {
this.setState({ posts: [e.post, ...this.state.posts] });
}
});
// this.interval = setInterval(()=>this.getPosts(), 10000);
}
请注意,我使用了.PostCreated
(而不是 PostCreated )。默认情况下,laravel在广播名称上具有约定。我更喜欢显式的编程风格,因此通常会为所有事件设置broadcastAs
。
答案 1 :(得分:0)
我能够弄清楚,并注意到我必须继续运行以下命令:
php artisan queue:listen