Per creare un rapporto di fiducia con la vostra comunità online o nel vostro blog, un elemento cruciale è un sistema di commenti in tempo reale progettato su Laravel.

Tuttavia, non è facile ottenerlo al primo tentativo a meno che non vi affidiate a sistemi di commenti self-hosted come Disqus o Commento, ognuno dei quali presenta una serie di svantaggi. Possiedono i vostri dati, offrono design e personalizzazioni limitate e, cosa più importante, non sono gratuiti.

Con queste limitazioni, se l’idea di costruire il vostro sistema di commenti in tempo reale – con i benefici del controllo dei dati, del design e della personalizzazione dell’aspetto per adattarsi al vostro blog – vi attrae, continuate a leggere.

Questo articolo vi insegnerà a sviluppare un sistema di commenti in tempo reale ben progettato e con diverse funzionalità di commento. Seguendo i principi della costruzione di un’applicazione di chat in tempo reale con Vue.js e Socket.io, useremo Laravel, Pusher e React per sviluppare il sistema di commenti in tempo reale.

Cominciamo!

Cosa Costruiremo

Costruiremo un sistema di commenti live, in tempo reale che può essere integrato in qualsiasi sito web o blog per creare fiducia nella comunità.

Panoramica dei Building Blocks: Laravel, Pusher e Vue

Prima di tuffarci nello sviluppo, discutiamo le tecnologie che useremo per sviluppare il nostro sistema di commenti in tempo reale.

Laravel

Laravel è un framework PHP open-source orientato a MVC. È utilizzato per costruire applicazioni web PHP da semplici a complesse, note per la loro sintassi elegante. Imparare a conoscere Laravel è essenziale per costruire questo sistema di commenti.

Pusher

Pusher permette a chi sviluppa di creare funzioni in tempo reale su scala. Questo articolo combinerà Laravel Echo per creare un evento di trasmissione in tempo reale al server Pusher e visualizzare il contenuto sul frontend con Vue.js.

Vue.js

Vue.js è il nostro framework frontend preferito. Vue.js è un framework frontend progressivo JavaScript noto per il suo approccio facile da imparare e diretto allo sviluppo frontend. Useremo Vue.js per sviluppare il nostro sistema di commenti in tempo reale.

Costruire il Sistema di Commenti

Se il sistema di commenti che abbiamo delineato sopra sembra fare al caso vostro, passiamo a costruirlo.

1. Installare e Configurare Laravel, Pusher e Echo

L’installazione e la configurazione di Laravel, Echo e Pusher è semplice poiché Laravel ha svolto tutti i compiti in background impostando e configurando Laravel Echo per lavorare perfettamente con Pusher. Per prima cosa, inizieremo installando e configurando Laravel, il nostro framework backend PHP. Potete prendere una nuova istanza di Laravel con questo comando, a condizione che abbiate installato globalmente la CLI di Laravel:

laravel new commenter

La vostra nuova istanza di Laravel sarà installata in una cartella chiamata commenter. Apriamo la cartella nel nostro VSCode e navighiamo fino ad essa nel nostro terminale:

cd commenter

code .

Prima di avviare il nostro server di sviluppo, installiamo e configuriamo alcuni pacchetti necessari che saranno utilizzati per il progetto.

Eseguite questo comando per installare l’SDK PHP di Pusher:

composer require pusher/pusher-php-server

Eseguite questo comando per installare i pacchetti NPM necessari per il frontend Vue.js:

npm install --save laravel-echo pusher-js

Poi configureremo Laravel Echo e Pusher. Aprite il vostro file resources/js/bootstrap.js e incollate i seguenti script:

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
});

Noterete dallo script qui sopra che stiamo solo configurando l’istanza di Axios con le nostre configurazioni predefinite. Successivamente, configureremo Laravel Echo per utilizzare Pusher e le sue configurazioni.

2. Configurazione e Migrazione del Database

Successivamente, creeremo e imposteremo il nostro database per memorizzare i commenti per la persistenza. Useremo SQLite, anche se potete usare qualsiasi client di database di vostra scelta.

Create un file database.sqlite all’interno della cartella del database e aggiornate il vostro file .env come segue:

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=

Successivamente, eseguite questo comando per creare la migrazione Comment e aggiornatela con i seguenti script:

php artisan make:migration create_comments_table

Aprite il file database/migrations/xxxx_create_comments_table_xxxx.php e incollate questo codice:

<?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');
    }
}

Questo creerà una nuova tabella del database dei commenti e aggiungerà le colonne contenuto e autore.

Infine, per creare la migrazione, eseguite questo comando:

php artisan migrate

3. Creazione di Modelli

In Laravel, i modelli sono importanti: sono il modo più sicuro per comunicare con il nostro database e gestire i dati.

Per creare un modello in Laravel, eseguiremo il seguente comando:

php artisan make:model Comment

Poi aprite il file app/models/Comment.php e incollate il seguente codice:

<?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'];
}

The $fillable array allows us to create and update the model in mass.

4. Creazione dei Controller

I controller sono cruciali perché ospitano tutta la logica, di business e non, delle nostre applicazioni, quindi creiamone uno per gestire la logica di commento:

php artisan make:controller CommentController

Poi aprite il file app/Http/Controllers/CommentController.php e incollate il seguente codice:

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

Il controller ha tre diversi metodi: restituire una vista dei commenti, recuperare tutti i commenti e memorizzare un nuovo commento, rispettivamente. La cosa più importante è che ogni volta che memorizziamo un nuovo commento lanciamo un evento, che il frontend ascolterà per aggiornare la relativa pagina con il nuovo commento in tempo reale usando Pusher e Laravel Echo.

5. Creazione delle Route

Per configurare correttamente le nostre route, abbiamo bisogno di aggiornare molti file, quindi cominciamo.

Per prima cosa, aggiorneremo il file api.php nella cartella routes. Aprite il file e aggiungete il seguente codice:

use App\Http\Controllers\CommentController;
//...

Route::get('/', [CommentController::class, 'index']);
Route::get('/comments', [CommentController::class, 'fetchComments']);
Route::post('/comments', [CommentController::class, 'store']);

Poi aprite il file channels.php nella stessa cartella e aggiungete il seguente codice per autorizzare l’evento che abbiamo lanciato prima:

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

Poi aprite il file web.php nella stessa cartella e aggiungete il seguente codice per reindirizzare la nostra richiesta alla homepage, dove Vue.js la raccoglierà:

use App\Http\Controllers\CommentController;
//...

Route::get('/', [CommentController::class, 'index']);

Infine, creeremo un nuovo file blade nella cartella resources/views chiamato comments.blade.php e aggiungeremo il seguente codice:

<!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 id="app">
        <div class="container">
            <div class="question-wrapper">
                <h5 class="is-size-2" style="color: #220052;">
                    What do you think about <span style="color: #47b784;">Dogs</span>?</h5>
                <br>
                <a href="#Form" class="button is-medium has-shadow has-text-white" style="background-color: #47b784">Comment</a>
            </div>
            <br><br>
            <comments></comments>
            <new-comment></new-comment>
        </div>
    </div>
    <script async src="{{mix('js/app.js')}}"></script>
</body>
</html>

Lo script aggiunge un titolo al post e un componente Vue per visualizzare e aggiungere nuovi commenti al titolo del post creato in precedenza.

Eseguite i seguenti comandi per verificare che sia tutto corretto:

npm run watch

php artisan serve

Se vedete questa pagina, siete pronti a passare al prossimo passo di questo articolo.

Sistema di commenti in tempo reale con Laravel
Sistema di commenti in tempo reale con Laravel

6. Impostare Vue (Frontend)

Creeremo e imposteremo la nostra istanza Vue per creare e visualizzare tutti i commenti fatti su questo post.

Inizieremo impostando il nostro negozio Vuex. Create i seguenti file nella cartella resource/js/store.

Create Stato di Commento

Create actions.js e aggiungete il seguente codice:

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;

Il file Action fa una chiamata all’endpoint dei commenti nel backend.

Successivamente, create un file getters.js e aggiungete il seguente codice:

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

Il file Getter è usato per recuperare tutti i commenti nello stato.

Create il file mutations.js e incollatelo nel seguente codice:

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

Successivamente, create un file state.js e incollatelo nel seguente codice:

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

Infine, aggiungeremo tutto al file index.js esportato nell’istanza Vue, creeremo un file index.js e aggiungeremo quanto segue:

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
});

Create i Componenti

Infine, creeremo i componenti per i commenti per visualizzare e aggiungere nuovi commenti. Iniziamo creando il singolo componente di commento.

Creiamo una cartella dentro la cartella resource/js chiamata components, aggiungiamo il comment.vue e aggiungiamo il seguente codice:

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

Successivamente, create il seguente file chiamato comments.vue nella stessa cartella e aggiungete il seguente codice:

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

Infine, create un file chiamato NewComment.vue e aggiungete il seguente codice:

<template>
  <div id="commentForm" 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
              style="height: 100px"
              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
            style="background-color: #47b784"
            :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>

Ora aprite il file app.js e aggiungete il seguente codice per registrare i componenti Vue che avete creato in precedenza:

// 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
});

Riepilogo

E questo è tutto! Avete appena imparato a costruire un sistema di commenti live per il vostro sito usando Laravel.

Abbiamo discusso i benefici della creazione e della gestione di un sistema di commenti per aumentare la fiducia nella vostra comunità o blog. Abbiamo anche visto come sviluppare un sistema di commenti ben progettato e in tempo reale da zero, utilizzando diverse funzionalità di commento.

Potete clonare il codice sorgente di questo progetto in questo repo Github.

Cosa ne pensate del sistema di commenti live di Laravel che abbiamo costruito insieme? Fatecelo sapere nei commenti!

Solomon Eseme

Sono un software engineer e un content creator orientato a costruire prodotti innovativi e ad alte prestazioni seguendo le migliori pratiche e gli standard del settore. Amo anche scrivere su Masteringbackend.com. Seguitemi su X, LinkedIn e About me.