Счетчик лайков не обновляется на другом клиенте (Laravel + Vue + Redis + Soket.io + Node) - PullRequest
0 голосов
/ 04 января 2019

Я пытаюсь сделать приложение в реальном времени.Когда пользователь нажимает кнопку «Нравится», счетчик «Нравится» обновляется.Теперь это работает только для текущего пользователя.Но другой пользователь не видит, что количество лайков изменилось (например, если он подключен через другой браузер).

После нажатия кнопки лайка я вижу сообщения сервера терминалов:

Message received: {"event":"App\\Events\\PostLiked","data":{"result":1,"socket":null},"socket":null}

Но счетчик лайков обновляется только для одного пользователя в текущем браузере.Я сделал два компонента Vue : 1. Кнопка «Мне нравится» (которая любит публикацию) - LikePost.vue 2. Метка счетчика лайков (которая показывает количество лайков) - LikePostCount.vue

Это снимок экрана

Я использую Laravel 5.5 + Vue JS 2.5.16

У меня естьустановлены следующие библиотеки и пакеты:

  • узел
  • redis-сервер
  • экспресс 4.16.3
  • ioredis 3.2.2
  • socket.io 2.1.1
  • socket.io-client 2.2.0

server.js

var http = require('http').Server();
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('news-action');
redis.on('message', function(channel, message) {
 console.log('Message received: ' + message);
 console.log('Channel :' + channel);
 message = JSON.parse(message);
 io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function(){
    console.log('Listening on Port: 3000');
});

/ resources / assets / js / bootstrap.js

window._ = require('lodash');
window.io = require('socket.io-client');

try {
       require('bootstrap-sass');
} catch (e) {}

window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

window.Vue = require('vue');
window.events = new Vue();

window.flash = function (message) {
    window.events.$emit('flash', message);
};

import Vue from 'vue'
import VueNoty from 'vuejs-noty'

//connects events bus
export const bus = new Vue();
Vue.use(VueNoty)

/ resources / assets / js / app.js

require('./bootstrap');

window.Vue = require('vue');

Vue.component('likepost', require('./components/LikePost.vue'));
Vue.component('likepostcount', require('./components/LikePostCount.vue'));

app = new Vue({
    el: '#app',
});

/ resources / assets / js / components / LikePost.vue

<template> 
        <span>

            <button v-if="isliked" 
                @click.prevent="dislike(post_id)"
                type="button" 
                class="btn btn-block btn-danger btn-xs" 
                name="like-button">
                    <i class="fa fa-heart"></i>
            </button>
            <button v-else
                @click.prevent="like(post_id)" 
                type="button" 
                class="btn btn-block btn-success btn-xs" 
                name="like-button">
                    <i class="fa fa-heart-o">
                        </i>
                </button>

        </span>    
 </template> 

<script>
    import { bus } from '../bootstrap';
    import 'vuejs-noty/dist/vuejs-noty.css'
    export default {
        props: ["post_id", "liked"],

        data: function() {
            return { 
                isliked: '',
            }
        },

        mounted() {
            this.isliked = this.islike ? true : false;
        },
        computed: {
            islike() {
                return this.liked;
            },
        },
        methods: {
            like(post_id) {
            axios
                .post('/blog/posts/like/' + post_id)
                .then(response => { this.isliked = true; 
                      bus.$emit('postliked');
                })
                .catch(response => console.log(response.data));
            },
            dislike(post_id) {
            axios
                .post('/blog/posts/like/' + post_id)
                .then(response => { this.isliked = false; 
                                    bus.$emit('postliked'); 
                })
                .catch(response => console.log(response.data));
            },
        }
    };
</script>

/ resources / assets / js / components / LikePostCount.vue

<template> 
        <span>
            <i class="fa fa-heart"></i> {{ likescount }}
        </span>    
 </template> 

<script>
    import { bus } from '../bootstrap';
    import 'vuejs-noty/dist/vuejs-noty.css'
    export default {
        props: {
            post_id: {
                    type: Number,
                    default: () => {}
                }
            },

        data: function() {
            return { 
                likescount: 0,
            }
        },

        created(){
            bus.$on('postliked', (data) => {
               this.updatelikescount(this.post_id); 
            });
        },
        mounted : function() {
            var socket = io('http://localhost:3000');
            socket.on("news-action:App\\Events\\NewEvent", function(data) {
                this.likescount = data.result;

            }.bind(this));

           this.updatelikescount(this.post_id);

        },

        methods: {

            updatelikescount(post_id) {

            axios
                .get('/blog/post/likecount/' + post_id)
                .then(response => {
                    this.likescount = response.data.data[0][0]
                })        
                .catch(response => console.log(response.data));
             },

        }
    };
</script>

/ app / Http / Controllers / LikeController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Like;
use App\BlogPost;
use App\Events\PostLiked;

class LikeController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('forbid-banned-user');
    }

    public function likePost($id)
    {
        // here you can check if product exists or is valid or whatever

        $this->handleLike('App\BlogPost', $id);
        $post = BlogPost::find($id);
        $like_count = $post->likes->count();
        event(new PostLiked($like_count));
        return redirect()->back();
    }

    public function handleLike($type, $id)
    {
        $existing_like = Like::withTrashed()->whereLikeableType($type)->whereLikeableId($id)->whereUserId(Auth::id())->first();

        if (is_null($existing_like)) {
            Like::create([
                'user_id'       => Auth::id(),
                'likeable_id'   => $id,
                'likeable_type' => $type,
            ]);
        } else {
            if (is_null($existing_like->deleted_at)) {
                $existing_like->delete();
            } else {
                $existing_like->restore();
            }
        }
    }

}

/ app / Events / PostLiked.php

<?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;

class PostLiked implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $result;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->result = $data;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        //return new PrivateChannel('channel-name');
        return ['news-action'];
    }
}

/ приложение / Http / Controllers / BlogPostController.php

<?php

namespace App\Http\Controllers;

use App\BlogPost;
use Illuminate\Support\Facades\Auth;

class BlogPostController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }


    public function postGetLikesCountEvent(BlogPost $post)
    {
        //dd($request);
        $data2[] = [
            $post->likes->count()
        ];

        return Response::json([
            'data' => $data2
        ], 200);

    }
}

/ routs / web.php

<?php
//BlogPost - likes - Like button clicked
Route::post('blog/posts/like/{post}', 'LikeController@likePost');
//BlogPost - likes - get likes count
Route::get('blog/post/likecount/{post}', 'BlogPostController@postGetLikesCountEvent');

1 Ответ

0 голосов
/ 04 января 2019

произошла ошибка в названии события в LikePostCount.vue

фиксированный

socket.on("news-action:App\\Events\\NewEvent"...

до

socket.on("news-action:App\\Events\\PostLiked"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...