Projeto

Estrutura de comentários para artigos

Estrutura de comentários para artigos

Fabrício de Medeiros

Para criar a estrutura de comentários para artigos no padrão MVC, vou seguir a arquitetura básica de uma aplicação MVC, garantindo a sanitização dos dados no controlador e utilizando getters e setters no modelo. Como você mencionou, faremos a sanitização de forma manual inicialmente, e posteriormente podemos discutir a inclusão de bibliotecas open source para melhorar o processo de sanitização, caso necessário.

A estrutura será semelhante à que já existe no seu projeto de gerenciamento de artigos, mas será aplicada à funcionalidade de comentários.

App
├── src
│   ├── Controller
│   │   ├── CommentController.php
│   ├── Model
│   │   ├── Comment.php
│   ├── View
│   │   ├── CommentView.php
├── config
│   └── database.php
├── public
│   └── index.php
└── vendor

1. Model (Comment.php)

Comment.php

Aqui criaremos a classe Comment que representará a tabela de comentários no banco de dados. Utilizaremos getters e setters para garantir a validação dos dados antes de armazená-los no banco.

<?php

namespace App\Model;

class Comment
{
    private $id;
    private $article_id;
    private $author;
    private $content;
    private $created_at;

    // Getters and Setters
    public function getId(){return $this->id;}
    public function setId($id){$this->id = $id;}
    public function getArticleId(){return $this->article_id;}
    public function setArticleId($article_id)
    {
        if (is_numeric($article_id)) {
            $this->article_id = $article_id;
        }
    }
    public function getContent(){return $this->content;}
    public function setContent($content){$this->content = htmlspecialchars(trim($content), ENT_QUOTES, 'UTF-8');}
    public function getCreatedAt(){return $this->created_at;}
    public function setCreatedAt($created_at){$this->created_at = $created_at;}
    }
}

2. Controller

CommentController.php)

Aqui implementamos a lógica para criar, editar, deletar e listar comentários, além de sanitizar os dados no controlador antes de processá-los.

<?php

namespace App\Controller;

use App\Model\Comment;
use App\Service\DatabaseService;

class CommentController
{
    private $db;

    public function __construct()
    {
        $this--->db = DatabaseService::getConnection();
    }

    // Create a new comment
    public function create($data)
    {
        $comment = new Comment();
        
        // Sanitize input
        $article_id = filter_var($data['article_id'], FILTER_SANITIZE_NUMBER_INT);
        $author = filter_var($data['author'], FILTER_SANITIZE_STRING);
        $content = filter_var($data['content'], FILTER_SANITIZE_STRING);

        // Set data using getters and setters
        $comment->setArticleId($article_id);
        $comment->setAuthor($author);
        $comment->setContent($content);
        $comment->setCreatedAt(date('Y-m-d H:i:s'));

        // Insert into database
        $stmt = $this->db->prepare("INSERT INTO tbl_comments (article_id, author, content, created_at) VALUES (?, ?, ?, ?)");
        $stmt->bind_param("isss", $article_id, $author, $content, $comment->getCreatedAt());
        
        if ($stmt->execute()) {
            return "Comment added successfully!";
        } else {
            return "Failed to add comment.";
        }
    }

    // Read comments by article
    public function getCommentsByArticle($article_id)
    {
        $article_id = filter_var($article_id, FILTER_SANITIZE_NUMBER_INT);
        
        $stmt = $this->db->prepare("SELECT * FROM tbl_comments WHERE article_id = ?");
        $stmt->bind_param("i", $article_id);
        $stmt->execute();
        
        $result = $stmt->get_result();
        $comments = [];
        while ($row = $result->fetch_assoc()) {
            $comments[] = $row;
        }
        return $comments;
    }

    // Delete a comment
    public function delete($id)
    {
        $id = filter_var($id, FILTER_SANITIZE_NUMBER_INT);
        
        $stmt = $this->db->prepare("DELETE FROM tbl_comments WHERE id = ?");
        $stmt->bind_param("i", $id);
        
        if ($stmt->execute()) {
            return "Comment deleted successfully!";
        } else {
            return "Failed to delete comment.";
        }
    }
}

3. View (CommentView.php)

CommentView.php

A CommentView.php será responsável por renderizar os comentários para o usuário, listando-os abaixo do artigo e fornecendo um formulário para adicionar novos comentários.

?php

namespace LibrarySystem\View;

class CommentView
{
public static function renderCommentForm($article_id)
{
        echo '
        <form action="/comment/create" method="POST">
            <input type="hidden" name="article_id" value="' . htmlspecialchars($article_id) . '">
            <label for="author">Author:</label>
            <input type="text" name="author" required>
            
            <label for="content">Comment:</label>
            <textarea name="content" required></textarea>
            
            <button type="submit">Add Comment</button>
        </form>';
    }

    public static function renderComments($comments)
    {
        foreach ($comments as $comment) {
            echo '
            <div class="comment">
                <p><strong>' . htmlspecialchars($comment['author']) . ':</strong></p>
                <p>' . htmlspecialchars($comment['content']) . '</p>
                <small>Posted on: ' . htmlspecialchars($comment['created_at']) . '</small>
            </div>';
        }
    }
}

4. Banco de Dados (SQL)

A tabela tbl_comments no banco de dados terá a seguinte estrutura:

CREATE TABLE tbl_comments (
    id INT AUTO_INCREMENT PRIMARY KEY,
    article_id INT NOT NULL,
    author VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    created_at DATETIME NOT NULL,
    FOREIGN KEY (article_id) REFERENCES tbl_articles(id)
);


5. Roteamento

No arquivo de roteamento (supondo que já esteja implementado), você pode definir as seguintes rotas:

$router->post('/comment/create', 'CommentController@create');
$router->get('/article/{id}/comments', 'CommentController@getCommentsByArticle');
$router->post('/comment/{id}/delete', 'CommentController@delete');

Considerações Finais

  1. Sanitização Manual: No controlador, usamos a função filter_var() para sanitizar os dados antes de passá-los ao modelo.
  2. Bibliotecas Open Source: Existem bibliotecas como HTMLPurifier para uma sanitização mais avançada de HTML e inputs de usuários. Podemos avaliar a implementação dessas bibliotecas caso o código atual precise de melhorias.
Editar Voltar