Construir um sistema de comentários ao vivo em Laravel
Publicados: 2021-09-22Para construir confiança em sua comunidade online ou blog, um elemento crucial que você vai querer é um sistema de comentários ao vivo Laravel bem projetado.
No entanto, não é fácil acertar na primeira tentativa, a menos que você confie em sistemas de comentários auto-hospedados, como Disqus ou Commento, cada um com seu próprio conjunto de desvantagens. Eles possuem seus dados, oferecem designs e personalizações limitados e, o mais importante, não são gratuitos.
Com essas limitações, se a ideia de construir seu sistema de comentários em tempo real — com os benefícios de controlar seus dados, projetar e personalizar a aparência para se adequar ao seu blog — agrada a você, continue lendo.
Este artigo ensinará como desenvolver um sistema de comentários bem projetado e em tempo real com diferentes funcionalidades de comentários. Seguindo os princípios de construção de um aplicativo de bate-papo em tempo real com Vue.js e Socket.io, usaremos Laravel, Pusher e React para desenvolver o sistema de comentários em tempo real.
Vamos mergulhar!
O que vamos construir
Construiremos um sistema de comentários em tempo real que pode ser integrado a qualquer site ou blog para criar confiança na comunidade.
Visão geral dos blocos de construção: Laravel, Pusher e Vue
Antes de nos aprofundarmos no desenvolvimento, vamos discutir as tecnologias que usaremos para desenvolver nosso sistema de comentários em tempo real.
Laravel
Laravel é um framework PHP orientado a MVC de código aberto. É usado para construir aplicações web PHP simples a complexas, conhecidas por sua sintaxe elegante. Aprender o que Laravel é essencial para construir este sistema de comentários.
Empurrador
O Pusher permite que os desenvolvedores criem recursos em tempo real em escala. Este artigo combinará o Laravel Echo para criar um evento de transmissão em tempo real para o servidor Pusher e exibir o conteúdo no frontend com o Vue.js.
Vue.js
Vue.js é a nossa estrutura de front-end preferida. Vue.js é uma estrutura de front-end de JavaScript progressiva conhecida por sua abordagem fácil de aprender e direta para o desenvolvimento de front-end. Usaremos Vue.js para desenvolver nosso sistema de comentários em tempo real.
Construindo o sistema de comentários
Se o sistema de comentários que descrevemos acima parece com o que você deseja, vamos seguir em frente para construí-lo.
1. Instalar e configurar Laravel, Pusher e Echo
A instalação e configuração do Laravel, Echo e Pusher é simples, pois o Laravel fez todas as tarefas em segundo plano configurando e configurando o Laravel Echo para funcionar perfeitamente com o Pusher.
Primeiramente, vamos começar instalando e configurando o Laravel, nosso framework PHP de backend. Você pode pegar uma nova instância do Laravel com este comando, desde que tenha instalado a CLI do Laravel globalmente:
laravel new commenter
Sua nova instância do Laravel será instalada em uma pasta chamada commenter. Vamos abrir a pasta em nosso VSCode e navegar até ela em nosso terminal:
cd commenter code .
Antes de iniciarmos nosso servidor de desenvolvimento, vamos instalar e configurar alguns pacotes necessários que serão utilizados para o projeto.
Execute este comando para instalar o Pusher PHP SDK:
composer require pusher/pusher-php-server
Execute este comando para instalar os pacotes NPM necessários para o front-end Vue.js:
npm install --save laravel-echo pusher-js
Em seguida, vamos configurar o Laravel Echo e Pusher. Abra seu arquivo resources/js/bootstrap.js e cole os seguintes scripts:
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 });
Você notará no script acima que estamos apenas configurando a instância do Axios com nossas configurações padrão. Em seguida, vamos configurar o Laravel Echo para usar o Pusher e suas configurações.
2. Configuração e migração do banco de dados
Em seguida, vamos criar e configurar nosso banco de dados para armazenar os comentários para persistência. Usaremos o SQLite, embora você possa usar qualquer cliente de banco de dados de sua escolha.
Crie um arquivo database.sqlite dentro da pasta do banco de dados e atualize seu arquivo .env da seguinte forma:
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=
Em seguida, execute este comando para criar a migração de comentários e atualize-a com os seguintes scripts:
php artisan make:migration create_comments_table
Abra o arquivo database/migrations/xxxx_create_comments_table_xxxx.php e cole este código:
<?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'); } }
Isso criará uma nova tabela de banco de dados de comentários e adicionará colunas de conteúdo e autor.
Por fim, para criar a migração, execute este comando:
php artisan migrate
3. Criando Modelos
No Laravel, os modelos são importantes - eles são a maneira mais segura de se comunicar com nosso banco de dados e lidar com o gerenciamento de dados.
Para criar um modelo em Laravel, executaremos o seguinte comando:
php artisan make:model Comment
Em seguida, abra o arquivo app/models/Comment.php e cole o seguinte código:
<?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']; }
O array $fillable nos permite criar e atualizar o modelo em massa.
4. Criando Controladores
Os controladores são cruciais porque abrigam toda a lógica, negócios e outros de nossos aplicativos, então vamos criar um para lidar com a lógica de comentários:
php artisan make:controller CommentController
Em seguida, abra o arquivo app/Http/Controllers/CommentController.php e cole o seguinte código:
<?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; } }
O controlador tem três métodos diferentes: retornar uma visualização de comentários, buscar todos os comentários e armazenar um novo comentário, respectivamente. Mais importante, acionamos um evento cada vez que armazenamos um novo comentário, que o frontend ouvirá para atualizar a página relevante com o novo comentário em tempo real usando Pusher e Laravel Echo.
5. Criando Rotas
Para configurar nossas rotas corretamente, precisaremos atualizar muitos arquivos, então vamos começar.
Primeiramente, vamos atualizar o arquivo api.php na pasta de rotas. Abra o arquivo e adicione o seguinte código:
use App\Http\Controllers\CommentController; //... Route::get('/', [CommentController::class, 'index']); Route::get('/comments', [CommentController::class, 'fetchComments']); Route::post('/comments', [CommentController::class, 'store']);
Em seguida, abra o arquivo channels.php na mesma pasta e adicione o seguinte código para autorizar o evento que disparamos anteriormente:

Broadcast::channel('comment', function ($user) { return true; });
Em seguida, abra o arquivo web.php na mesma pasta e adicione o seguinte código para redirecionar nossa solicitação para a página inicial, onde o Vue.js irá buscá-la:
use App\Http\Controllers\CommentController; //... Route::get('/', [CommentController::class, 'index']);
Por fim, criaremos um novo arquivo blade na pasta resources/views chamado comments.blade.php e adicionaremos o seguinte código:
<!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>
O script adiciona um título de postagem e um componente Vue para exibir e adicionar novos comentários ao título de postagem criado acima.
Execute os seguintes comandos para testar se você obteve tudo corretamente:
npm run watch php artisan serve
Se você for apresentado a esta página, você está pronto para passar para a próxima etapa deste artigo.
Precisa de uma solução de hospedagem que lhe dê uma vantagem competitiva? Kinsta cobre você com velocidade incrível, segurança de última geração e dimensionamento automático. Confira nossos planos

6. Configurando o Vue (Frontend)
Vamos criar e configurar nossa instância Vue para criar e exibir todos os comentários feitos neste post.
Começaremos configurando nossa loja Vuex. Crie os seguintes arquivos na pasta resource/js/store.
Criar estado de comentário
Crie actions.js e adicione o seguinte código:
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;
O arquivo Action faz uma chamada para o endpoint de comentário no back-end.
Em seguida, crie um arquivo getters.js e adicione o seguinte código:
let getters = { comments: state => { return state.comments; } }; export default getters;
O arquivo Getter é usado para recuperar todos os comentários no estado.
Crie o arquivo mutations.js e cole-o no código a seguir:
let mutations = { GET_COMMENTS(state, comments) { state.comments = comments; }, ADD_COMMENT(state, comment) { state.comments = [...state.comments, comment]; } }; export default mutations;
Em seguida, crie um arquivo state.js e cole-o no código a seguir:
let state = { comments: [] }; export default state;
Por fim, adicionaremos tudo ao arquivo index.js exportado para a instância Vue, criaremos um arquivo index.js e adicionaremos o seguinte:
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 });
Criar componentes
Por fim, vamos criar nossos componentes de comentários para exibir e adicionar novos comentários. Vamos começar criando o componente de comentário único.
Crie uma pasta na pasta resource/js chamada components, adicione o comment.vue e adicione o seguinte código:
<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>
Em seguida, crie o seguinte arquivo chamado comments.vue na mesma pasta e adicione o seguinte código:
<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>
Por fim, crie um arquivo chamado NewComment.vue e adicione o seguinte código:
<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>
Agora, abra o arquivo app.js e adicione o seguinte código para registrar os componentes Vue que você criou anteriormente:
// 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 });
Resumo
E é isso! Você acabou de aprender como construir um sistema de comentários ao vivo para o seu site usando Laravel.
Discutimos os benefícios de criar e gerenciar um sistema de comentários em sua busca para criar confiança em sua comunidade ou blog. Também exploramos como desenvolver um sistema de comentários bem projetado e em tempo real desde o início, utilizando diferentes funcionalidades de comentários.
Você pode clonar o código-fonte deste projeto neste repositório do Github.
O que você acha do sistema de comentários ao vivo do Laravel que construímos juntos? Deixe-nos saber nos comentários!