Laravel Echo不听

时间:2019-05-02 17:51:22

标签: laravel

我正在尝试使用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);
    }

我希望创建新帖子的用户的关注者可以立即看到该帖子,而无需重新加载页面,但是什么也没有发生。

事件已创建,但未监听。我在做什么错了?

2 个答案:

答案 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