構建 Laravel 實時評論系統
已發表: 2021-09-22為了在您的在線社區或博客中建立信任,您需要的一個關鍵要素是精心設計的 Laravel 實時評論系統。
但是,除非您依賴自託管的評論系統,例如 Disqus 或 Commento,否則在第一次嘗試時就做到正確並不容易,每個系統都有其自身的缺點。 他們擁有您的數據,提供有限的設計和定制,最重要的是,它們不是免費的。
有了這些限制,如果構建實時評論系統的想法——具有控制數據、設計和自定義外觀以適應你的博客的好處——對你有吸引力,請繼續閱讀。
本文將教您如何開發具有不同評論功能的精心設計的實時評論系統。 遵循使用 Vue.js 和 Socket.io 構建實時聊天應用程序的原則,我們將使用 Laravel、Pusher 和 React 來開發實時評論系統。
讓我們潛入吧!
我們將建造什麼
我們將構建一個實時評論系統,該系統可以集成到任何網站或博客中,以建立對社區的信任。
構建塊概述: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 為您提供令人難以置信的速度、最先進的安全性和自動縮放功能。 查看我們的計劃

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 實時評論系統? 讓我們在評論中知道!