构建 Laravel 实时评论系统

已发表: 2021-09-22

为了在您的在线社区或博客中建立信任,您需要的一个关键要素是精心设计的 Laravel 实时评论系统。

但是,除非您依赖自托管的评论系统,例如 Disqus 或 Commento,否则在第一次尝试时就做到正确并不容易,每个系统都有其自身的缺点。 他们拥有您的数据,提供有限的设计和定制,最重要的是,它们不是免费的。

有了这些限制,如果构建实时评论系统的想法——具有控制数据、设计和自定义外观以适应你的博客的好处——对你有吸引力,请继续阅读。

本文将教您如何开发具有不同评论功能的精心设计的实时评论系统。 遵循使用 Vue.js 和 Socket.io 构建实时聊天应用程序的原则,我们将使用 Laravel、Pusher 和 React 来开发实时评论系统。

让我们潜入吧!

我们将建造什么

我们将构建一个实时评论系统,该系统可以集成到任何网站或博客中,以建立对社区的信任。

为了在您的在线社区或博客中建立信任,您需要的一个关键要素是精心设计的 Laravel 实时评论系统。 在此处了解如何开始点击推文

构建块概述:Laravel、Pusher 和 Vue

在深入开发之前,让我们讨论一下我们将用于开发实时评论系统的技术。

拉拉维尔

Laravel 是一个开源的面向 MVC 的 PHP 框架。 它用于构建从简单到复杂的 PHP Web 应用程序,以其优雅的语法而闻名。 了解 Laravel 对构建这个评论系统至关重要。

推杆

Pusher 使开发人员能够大规模创建实时功能。 本文将结合 Laravel Echo 创建实时广播事件到 Pusher 服务器,并使用 Vue.js 在前端显示内容。

Vue.js

Vue.js 是我们选择的前端框架。 Vue.js 是一个进步的 JavaScript 前端框架,以其易于学习和直接的前端开发方法而闻名。 我们将使用 Vue.js 来开发我们的实时评论系统。

构建评论系统

如果我们上面概述的评论系统听起来像您想要的,让我们继续构建它。

1. 安装和设置 Laravel、Pusher 和 Echo

Laravel、Echo 和 Pusher 的安装和设置非常简单,因为 Laravel 通过设置和配置 Laravel Echo 以完美地与 Pusher 一起完成所有后台任务。

首先,我们将从安装和配置我们的后端 PHP 框架 Laravel 开始。 你可以使用这个命令获取一个新的 Laravel 实例,前提是你已经全局安装了 Laravel CLI:

 laravel new commenter

你的新 Laravel 实例将安装在一个名为 commenter 的文件夹中。 让我们在 VSCode 中打开文件夹并在终端中导航到它:

 cd commenter code .

在我们启动我们的开发服务器之前,让我们安装和配置一些将用于项目的必要包。

运行以下命令安装 Pusher PHP SDK:

 composer require pusher/pusher-php-server

运行以下命令为 Vue.js 前端安装必要的 NPM 包:

 npm install --save laravel-echo pusher-js

接下来,我们将配置 Laravel Echo 和 Pusher。 打开您的resources/js/bootstrap.js文件并粘贴以下脚本:

 window._ = require("lodash"); window.axios = require("axios"); window.moment = require("moment"); window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest"; window.axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; window.axios.defaults.headers.common.crossDomain = true; window.axios.defaults.baseURL = "/api"; 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"); } /** * Echo exposes an expressive API for subscribing to channels and listening * for events that Laravel broadcasts. Echo and event broadcasting * allows your team to build robust real-time web applications quickly. */ import Echo from "laravel-echo"; window.Pusher = require("pusher-js"); window.Echo = new Echo({ broadcaster: "pusher", key: process.env.MIX_PUSHER_APP_KEY, cluster: process.env.MIX_PUSHER_APP_CLUSTER, forceTLS: true });

您会从上面的脚本中注意到,我们只是使用我们的默认配置来配置 Axios 实例。 接下来,我们将配置 Laravel Echo 以使用 Pusher 及其配置。

2. 数据库设置和迁移

接下来,我们将创建并设置我们的数据库来存储持久化的评论。 我们将使用 SQLite,尽管您可以使用您选择的任何数据库客户端。

在数据库文件夹中创建一个database.sqlite文件并更新您的.env文件,如下所示:

 DB_CONNECTION=sqlite DB_DATABASE=/Users/all/paths/to/project/commenter_be/database/database.sqlite DB_HOST=127.0.0.1 DB_PORT=3306 DB_USERNAME=root DB_PASSWORD=

接下来,运行此命令以创建 Comment 迁移并使用以下脚本对其进行更新:

 php artisan make:migration create_comments_table

打开database/migrations/xxxx_create_comments_table_xxxx.php文件并粘贴以下代码:

 <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateCommentsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('comments', function (Blueprint $table) { $table->id(); $table->string('content'); $table->string('author'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('comments'); } }

这将创建一个新的评论数据库表并添加内容和作者列。

最后,要创建迁移,请运行以下命令:

 php artisan migrate

3. 创建模型

在 Laravel 中,模型很重要——它们是与我们的数据库通信和处理数据管理的最可靠的方式。

要在 Laravel 中创建模型,我们将运行以下命令:

 php artisan make:model Comment

接下来,打开app/models/Comment.php文件并粘贴以下代码:

 <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Comment extends Model { use HasFactory; protected $fillable = ['content', 'author']; } $fillable 数组允许我们批量创建和更新模型。

4. 创建控制器

控制器至关重要,因为它们包含我们应用程序的所有逻辑、业务和其他方面,所以让我们创建一个来处理评论逻辑:

php artisan make:controller CommentController

接下来,打开app/Http/Controllers/CommentController.php文件并粘贴以下代码:

 <?php namespace App\Http\Controllers; use App\Models\Comment; use App\Events\CommentEvent; use Illuminate\Http\Request; class CommentController extends Controller { // public function index() { return view('comments'); } public function fetchComments() { $comments = Comment::all(); return response()->json($comments); } public function store(Request $request) { $comment = Comment::create($request->all()); event(new CommentEvent($comment)); return $comment; } }

控制器具有三种不同的方法:分别返回评论视图、获取所有评论和存储新评论。 最重要的是,我们每次存储新评论时都会触发一个事件,前端将使用 Pusher 和 Laravel Echo 使用新评论实时更新相关页面。

5. 创建路由

为了正确配置我们的路由,我们需要更新很多文件,所以让我们开始吧。

首先,我们将更新路由文件夹中的api.php文件。 打开文件并添加以下代码:

 use App\Http\Controllers\CommentController; //... Route::get('/', [CommentController::class, 'index']); Route::get('/comments', [CommentController::class, 'fetchComments']); Route::post('/comments', [CommentController::class, 'store']);

接下来,打开同一文件夹中的channels.php文件并添加以下代码来授权我们之前触发的事件:

 Broadcast::channel('comment', function ($user) { return true; });

接下来,打开同一文件夹中的web.php文件并添加以下代码以将我们的请求重定向到主页,Vue.js 将在主页上接收它:

 use App\Http\Controllers\CommentController; //... Route::get('/', [CommentController::class, 'index']);

最后,我们将在resources/views文件夹中创建一个名为comments.blade.php的新刀片文件,并添加以下代码:

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Commenter</title> <meta name="csrf-token" content="{{ csrf_token() }}"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css" /> <style> .container { margin: 0 auto; position: relative; width: unset; } #app { width: 60%; margin: 4rem auto; } .question-wrapper { text-align: center; } </style> </head> <body> <div> <div class="container"> <div class="question-wrapper"> <h5 class="is-size-2"> What do you think about <span>Dogs</span>?</h5> <br> <a href="#Form" class="button is-medium has-shadow has-text-white">Comment</a> </div> <br><br> <comments></comments> <new-comment></new-comment> </div> </div> <script async src="{{mix('js/app.js')}}"></script> </body> </html>

该脚本添加了一个帖子标题和一个 Vue 组件来显示和添加新评论到上面创建的帖子标题。

运行以下命令以测试您是否正确获取所有内容:

 npm run watch php artisan serve

如果您看到此页面,则您已准备好进入本文的下一步。

需要一个可以为您提供竞争优势的托管解决方案? Kinsta 为您提供令人难以置信的速度、最先进的安全性和自动缩放功能。 查看我们的计划

Laravel 中的实时评论系统
Laravel 中的实时评论系统

6. 设置 Vue(前端)

我们将创建并设置我们的 Vue 实例来创建和显示在这篇文章上发表的所有评论。

我们将从设置我们的 Vuex 商店开始。 在 resource/js/store 文件夹中创建以下文件。

创建评论状态

创建 actions.js 并添加以下代码:

 let actions = { ADD_COMMENT({ commit }, comment) { return new Promise((resolve, reject) => { axios .post(`/comments`, comment) .then(response => { resolve(response); }) .catch(err => { reject(err); }); }); }, GET_COMMENTS({ commit }) { axios .get("/comments") .then(res => { { commit("GET_COMMENTS", res.data); } }) .catch(err => { console.log(err); }); } }; export default actions;

Action 文件调用后端的评论端点。

接下来,创建一个 getters.js 文件并添加以下代码:

 let getters = { comments: state => { return state.comments; } }; export default getters;

Getter 文件用于检索状态中的所有评论。

创建 mutation.js 文件并将其粘贴到以下代码中:

 let mutations = { GET_COMMENTS(state, comments) { state.comments = comments; }, ADD_COMMENT(state, comment) { state.comments = [...state.comments, comment]; } }; export default mutations;

接下来,创建一个 state.js 文件并将其粘贴到以下代码中:

 let state = { comments: [] }; export default state;

最后,我们将所有内容添加到导出到 Vue 实例的 index.js 文件中,创建一个 index.js 文件并添加以下内容:

 import Vue from "vue"; import Vuex from "vuex"; import actions from "./actions"; import mutations from "./mutations"; import getters from "./getters"; import state from "./state"; Vue.use(Vuex); export default new Vuex.Store({ state, mutations, getters, actions });

创建组件

最后,我们将创建评论组件来显示和添加新评论。 让我们从创建单个评论组件开始。

resource/js文件夹中创建一个名为 components 的文件夹,添加comment.vue并添加以下代码:

 <template> <li class="comment-wrapper animate slideInLeft"> <div class="profile"> </div> <div class="msg has-shadow"> <div class="msg-body"> <p class="name"> {{ comment.author }} <span class="date">{{ posted_at }}</span> </p> <p class="content">{{ comment.content }}</p> </div> </div> </li> </template> <script> export default { name: "Comment", props: ["comment"], computed: { posted_at() { return moment(this.comment.created_at).format("MMMM Do YYYY"); }, }, }; </script> <style lang="scss" scoped> .comment-wrapper { list-style: none; text-align: left; overflow: hidden; margin-bottom: 2em; padding: 0.4em; .profile { width: 80px; float: left; } .msg-body { padding: 0.8em; color: #666; line-height: 1.5; } .msg { width: 86%; float: left; background-color: #fff; border-radius: 0 5px 5px 5px; position: relative; &::after { content: " "; position: absolute; left: -13px; top: 0; border: 14px solid transparent; border-top-color: #fff; } } .date { float: right; } .name { margin: 0; color: #999; font-weight: 700; font-size: 0.8em; } p:last-child { margin-top: 0.6em; margin-bottom: 0; } } </style>

接下来,在同一文件夹中创建名为comments.vue的以下文件并添加以下代码:

 <template> <div class="container"> <ul class="comment-list"> <Comment :key="comment.id" v-for="comment in comments" :comment="comment" ></Comment> </ul> </div> </template> <script> import { mapGetters } from "vuex"; import Comment from "./Comment"; export default { name: "Comments", components: { Comment }, mounted() { this.$store.dispatch("GET_COMMENTS"); this.listen(); }, methods: { listen() { Echo.channel("comment").listen("comment", (e) => { console.log(e); this.$store.commit("ADD_COMMENT", e); }); }, }, computed: { ...mapGetters(["comments"]), }, }; </script> <style scoped> .comment-list { padding: 1em 0; margin-bottom: 15px; } </style>

最后,创建一个名为NewComment.vue的文件并添加以下代码:

 <template> <div class="box has-shadow has-background-white"> <form @keyup.enter="postComment"> <div class="field has-margin-top"> <div class="field has-margin-top"> <label class="label">Your name</label> <div class="control"> <input type="text" placeholder="Your name" class="input is-medium" v-model="comment.author" /> </div> </div> <div class="field has-margin-top"> <label class="label">Your comment</label> <div class="control"> <textarea name="comment" class="input is-medium" autocomplete="true" v-model="comment.content" placeholder="lorem ipsum" ></textarea> </div> </div> <div class="control has-margin-top"> <button :class="{ 'is-loading': submit }" class="button has-shadow is-medium has-text-white" :disabled="!isValid" @click.prevent="postComment" type="submit" > Submit </button> </div> </div> </form> <br /> </div> </template> <script> export default { name: "NewComment", data() { return { submit: false, comment: { content: "", author: "", }, }; }, methods: { postComment() { this.submit = true; this.$store .dispatch("ADD_COMMENT", this.comment) .then((response) => { this.submit = false; if (response.data) console.log("success"); }) .catch((err) => { console.log(err); this.submit = false; }); }, }, computed: { isValid() { return this.comment.content !== "" && this.comment.author !== ""; }, }, }; </script> <style scoped> .has-margin-top { margin-top: 15px; } </style>

现在,打开app.js文件并添加以下代码来注册您之前创建的 Vue 组件:

 // resource/js/app.js require("./bootstrap"); window.Vue = require("vue"); import store from "./store/index"; Vue.component("comment", require("./components/Comment")); Vue.component("comments", require("./components/Comments")); Vue.component("new-comment", require("./components/NewComment")); const app = new Vue({ el: "#app", store });
想建立自己的个性化评论系统吗? 这篇文章包含您开始使用所需的一切点击鸣叫

概括

就是这样! 您刚刚学习了如何使用 Laravel 为您的网站构建实时评论系统。

我们已经讨论了创建和管理评论系统的好处,以便您在社区或博客中建立信任。 我们还探索了如何利用不同的评论功能从头开始开发设计良好的实时评论系统。

你可以在这个 Github repo 中克隆这个项目的源代码。

您如何看待我们共同构建的 Laravel 实时评论系统? 让我们在评论中知道!