أنشئ نظام تعليق مباشر من Laravel
نشرت: 2021-09-22لبناء الثقة في مجتمعك أو مدونتك عبر الإنترنت ، فإن أحد العناصر الحاسمة التي تريدها هو نظام التعليق المباشر المصمم جيدًا من Laravel.
ومع ذلك ، ليس من السهل القيام بذلك بشكل صحيح من المحاولة الأولى ما لم تعتمد على أنظمة التعليق ذاتية الاستضافة مثل Disqus أو Commento ، كل منها يأتي مع مجموعة من العيوب الخاصة به. إنهم يمتلكون بياناتك ويقدمون تصميمات وتخصيصات محدودة ، والأهم من ذلك أنهم ليسوا مجانيين.
مع هذه القيود ، إذا كانت فكرة بناء نظام التعليق في الوقت الفعلي - مع فوائد التحكم في بياناتك ، وتصميم وتخصيص الشكل والمظهر لتلائم مدونتك - تروق لك ، فاستمر في القراءة.
ستعلمك هذه المقالة كيفية تطوير نظام تعليق جيد التصميم وفي الوقت الفعلي بوظائف تعليق مختلفة. باتباع مبادئ بناء تطبيق دردشة في الوقت الفعلي باستخدام Vue.js و Socket.io ، سنستخدم Laravel و Pusher و React لتطوير نظام التعليق في الوقت الفعلي.
دعنا نتعمق!
ما سنبنيه
سننشئ نظام تعليق في الوقت الفعلي يمكن دمجه في أي موقع ويب أو مدونة لبناء الثقة في المجتمع.
نظرة عامة على اللبنات الأساسية: Laravel و Pusher و Vue
قبل أن نتعمق في التطوير ، دعونا نناقش التقنيات التي سنستخدمها لتطوير نظام التعليق في الوقت الفعلي.
Laravel
Laravel هو إطار عمل PHP مفتوح المصدر موجه لـ MVC. يتم استخدامه لبناء تطبيقات ويب PHP بسيطة ومعقدة معروفة ببنيتها الأنيقة. تعلم ما هو Laravel ضروري لبناء نظام التعليقات هذا.
انتهازي
يتيح Pusher للمطورين إنشاء ميزات في الوقت الفعلي على نطاق واسع. ستجمع هذه المقالة بين Laravel Echo لإنشاء حدث بث في الوقت الفعلي لخادم Pusher وعرض المحتوى على الواجهة الأمامية باستخدام Vue.js.
Vue.js
Vue.js هو إطار عمل الواجهة الأمامية الذي نختاره. Vue.js هو إطار عمل تقدمي للواجهة الأمامية لجافا سكريبت معروف بنهجه السهل التعلم والمباشر لتطوير الواجهة الأمامية. سنستخدم Vue.js لتطوير نظام التعليقات في الوقت الفعلي.
بناء نظام التعليق
إذا كان نظام التعليق الذي حددناه أعلاه يبدو كما تريد ، فلننتقل إلى بنائه.
1. تثبيت وإعداد Laravel و Pusher و Echo
يعد تثبيت Laravel و Echo و Pusher وإعداده أمرًا سهلاً حيث أن Laravel قام بجميع مهام الخلفية من خلال إعداد Laravel Echo وتكوينه للعمل مع Pusher بشكل مثالي.
أولاً ، سنبدأ بتثبيت وتكوين Laravel ، إطار عمل PHP الخلفي. يمكنك الحصول على نسخة جديدة من Laravel باستخدام هذا الأمر ، بشرط أن تكون قد قمت بتثبيت Laravel CLI عالميًا:
laravel new commenter
سيتم تثبيت مثيل Laravel الجديد في مجلد يسمى commenter. دعنا نفتح المجلد في VSCode الخاص بنا وننتقل إليه في المحطة الطرفية الخاصة بنا:
cd commenter code .
قبل أن نبدأ خادم التطوير الخاص بنا ، فلنقم بتثبيت وتهيئة بعض الحزم الضرورية التي سيتم استخدامها للمشروع.
قم بتشغيل هذا الأمر لتثبيت Pusher PHP SDK:
composer require pusher/pusher-php-server
قم بتشغيل هذا الأمر لتثبيت حزم NPM الضرورية للواجهة الأمامية Vue.js:
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=
بعد ذلك ، قم بتشغيل هذا الأمر لإنشاء ترحيل التعليق وتحديثه بالبرامج النصية التالية:
php artisan make:migration create_comments_table
افتح ملف قاعدة البيانات / التهجيرات / 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']; }
تسمح لنا المصفوفة القابلة للتعبئة $ بإنشاء النموذج وتحديثه بالكتلة.
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']);
أخيرًا ، سننشئ ملف شفرة جديدًا في مجلد الموارد / العروض يسمى 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;
يقوم ملف الإجراء باستدعاء نقطة نهاية التعليق في الخلفية.
بعد ذلك ، قم بإنشاء ملف getters.js وأضف الكود التالي:
let getters = { comments: state => { return state.comments; } }; export default getters;
يتم استخدام ملف Getter لاسترداد جميع التعليقات الموجودة في الحالة.
أنشئ ملف mutations.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;
أخيرًا ، سنضيف كل شيء إلى ملف index.js المُصدَّر إلى مثيل Vue ، وننشئ ملف 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 يسمى المكونات ، أضف 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 الذي أنشأناه معًا؟ اسمحوا لنا أن نعرف في التعليقات!