Projeto

Implementação do Sistema de CRUD dos Artigos.

Implementação do Sistema

O sistema será desenvolvido seguindo o padrão MVC (Model-View-Controller). Essa arquitetura divide o projeto em três componentes principais: Model, responsável pela gestão dos dados e lógica de negócios; View, que cuida da apresentação das informações ao usuário; e Controller, que intermedia a interação entre o Model e a View. Essa estrutura facilita a manutenção e escalabilidade do sistema.

O padrão MVC (Model-View-Controller) é uma arquitetura usada para organizar e estruturar o desenvolvimento de aplicações. Ele divide o sistema em três componentes principais:

Além dos componentes principais, Model, View, e Controller, a implementação incluirá também:

Implementação de Banco de Dados

A implementação do Banco de Dados será projetada para suportar a arquitetura MVC (Model-View-Controller) e garantir uma gestão eficiente dos dados. Os principais aspectos da implementação incluem:

Configurações Regionais:

Estrutura de Pastas

    App
    ├── public
    │   ├── dist
    │   ├── img
    │   ├── index.php
    │   └── favicon.ico
    ├── src
    │   ├── Model
    │   │   └── ArticleModel.php
    │   ├── View
    │   │   ├── Article
    │   │   │   ├── article.php
    │   │   │   ├── articles.php
    │   │   │   ├── create.php
    │   │   │   └── edit.php
    │   │   ├── Template
    │   │   │   ├── header.php
    │   │   │   └── footer.php
    │   │   └── ArticleView.php
    │   ├── Controller
    │   │   └── ArticleController.php
    │   ├── services
    │   │   └── Service
    │   │       └── Service.php
    │   └── config
    │       └── database.php
    ├── vendor
    │   ├── composer
    │   │   └── (arquivos e pastas relacionados ao Composer)
    │   └── autoload.php
    ├── routes.php
    ├── project.html
    └── composer.json
    

Estrutura do Projeto


ARQUITETURA MVC

Classes

1. Model

ArticleModel

A Classe ArticleModel, localizada em src/Model/ArticleModel.php, representa a entidade associada à tabela `tbl_artigos` no banco de dados. Esta classe é responsável por gerenciar todas as operações relacionadas aos artigos, refletindo a estrutura da tabela `tbl_artigos`. Ela contém propriedades que correspondem às colunas da tabela, como título, conteúdo, autor e datas de criação e atualização. A classe inclui métodos para salvar, atualizar, excluir e recuperar artigos do banco de dados.

Propriedades:

Métodos:

Getters: Métodos usados para acessar (ou “obter”) o valor de uma propriedade de uma classe.

Setters: Métodos usados para modificar (ou “definir”) o valor de uma propriedade de uma classe.

ArticleModel.php
        
    namespace App\Model;

    class ArticleModel {
        private $id_artigo;
        private $titulo;
        private $conteudo;
        private $autor;
        private $dataCriacao;
        private $dataAtualizacao;
        private $status;

        // Getters and setters for each property
        public function getId() { /*...*/ }
        public function setId($id) { /*...*/ }
        public function getTitulo() { /*...*/ }
        public function setTitulo($titulo) { /*...*/ }
        // Other getters and setters...

        // Method to save an article to the database
        public function save() {
            // SQL query to insert or update the article
        }

        // Method to fetch an article by ID
        public static function findById($id) {
            // SQL query to find the article by ID
        }

        // Method to fetch all articles
        public static function findAll() {
            // SQL query to find all articles
        }
    }

        
    
        
    <?php

    namespace App\Model;

    class ArtigoModel
    {
        private $db;

        public function __construct()
        {
            $this->db = new \PDO("mysql:host=localhost;dbname=seu_banco_de_dados", "usuario", "senha");
        }

        public function getAll()
        {
            // Lógica para obter todos os artigos
        }

        public function getById($id)
        {
            // Lógica para obter um artigo específico pelo ID
        }

        public function create($data)
        {
            // Lógica para criar um novo artigo
        }

        public function update($id, $data)
        {
            // Lógica para atualizar um artigo existente
        }

        public function delete($id)
        {
            // Lógica para deletar um artigo
        }
    }
        
    
    
    <?php

    namespace App\Model;
    
    class ArtigoModel
    {
        private $db;
    
        public function __construct()
        {
            $this->db = new \PDO("mysql:host=localhost;dbname=seu_banco_de_dados", "usuario", "senha");
        }
    
        public function getAll()
        {
            $stmt = $this->db->query('SELECT * FROM artigos');
            return $stmt->fetchAll(\PDO::FETCH_ASSOC);
        }
    
        public function getById($id)
        {
            $stmt = $this->db->prepare('SELECT * FROM artigos WHERE id = :id');
            $stmt->execute(['id' => $id]);
            return $stmt->fetch(\PDO::FETCH_ASSOC);
        }
    
        public function create($data)
        {
            $stmt = $this->db->prepare('INSERT INTO artigos (titulo, conteudo) VALUES (:titulo, :conteudo)');
            $stmt->execute([
                'titulo' => $data['titulo'],
                'conteudo' => $data['conteudo']
            ]);
        }
    
        public function update($id, $data)
        {
            $stmt = $this->db->prepare('UPDATE artigos SET titulo = :titulo, conteudo = :conteudo WHERE id = :id');
            $stmt->execute([
                'id' => $id,
                'titulo' => $data['titulo'],
                'conteudo' => $data['conteudo']
            ]);
        }
    
        public function delete($id)
        {
            $stmt = $this->db->prepare('DELETE FROM artigos WHERE id = :id');
            $stmt->execute(['id' => $id]);
        }
    }         
    

2. View

ArticleView

A classe ArticleView, localizada em src/View/ArticleView.php, é responsável por renderizar as páginas HTML relacionadas aos artigos. Esta classe gera a interface com o usuário, exibindo formulários para criação e edição de artigos, bem como listagens dos artigos disponíveis. Os métodos correspondentes a essa classe são fundamentais para a interação visual com o sistema, permitindo que os usuários vejam e manipulem os dados dos artigos de maneira intuitiva e organizada.

Métodos:

ArticleView.php
        
    namespace LibrarySystem\View;

    class ArticleView {
        public function renderCreateForm() {
            // HTML form for creating a new article
        }
    
        public function renderEditForm($artigo) {
            // HTML form for editing an existing article
        }
    
        public function renderList($artigos) {
            // HTML to list all articles
        }
    
        public function renderArticle($artigo) {
            // HTML to display a single article
        }
    }
        
    

Views correspondentes em src/View/Article para exibir os formulários e listagens de artigos.

Implementação

  1. Cadastro de Artigos: Utilize a rota /artigos/create para exibir o formulário de criação e /artigos/store para processar e salvar o novo artigo.
  2. Visualização de Artigos: Utilize a rota /artigos/{id} para exibir um artigo específico e /artigos para listar todos os artigos.
  3. Edição e Deleção: Roteie para /artigos/edit/{id} e /artigos/delete/{id} para edição e deleção de artigos.
src/View/Article/index.php
        
    <h1>Lista de Artigos</h1>

    <a href="?route=article_create">Criar Novo Artigo</a>
    
    <ul>
        <?php foreach ($artigos as $artigo): ?>
            <li>
                <a href="?route=article_show&id=<?php echo htmlspecialchars($artigo['id']); ?>">
                    <?php echo htmlspecialchars($artigo['titulo']); ?>
                </a>
                <a href="?route=article_edit&id=<?php echo htmlspecialchars($artigo['id']); ?>">Editar</a>
    
                    <form action="?route=article_delete" method="post" style="display:inline;">
                        <input type="hidden" name="id" value="<?php echo htmlspecialchars($artigo['id']); ?>">
                        <button type="submit">Deletar</button>
                    </form>
            </li>

<?php endforeach; ?> </ul>

src/View/Article/show.php

        
    <h1><?php echo htmlspecialchars($artigo['titulo']); ?></h1>
    <p><?php echo htmlspecialchars($artigo['conteudo']); ?></p>
    <a href="?route=article_edit&id=<?php echo htmlspecialchars($artigo['id']); ?>">Editar</a>
    <a href="?route=articles">Voltar</a>
        
    

src/View/Article/create.php

        
    <h1>Criar Novo Artigo</h1>

    <form action="?route=article_store" method="post">
        
        <label for="titulo">Título:</label>
        <input type="text" id="titulo" name="titulo" required>
        <br>
        
        <label for="conteudo">Conteúdo:</label>
        <textarea id="conteudo" name="conteudo" required></textarea>
        <br>
        
        <button type="submit">Salvar</button>
        
    </form>
        
    <a href="?route=articles">Voltar</a>
        
    

src/View/Article/edit.php

        
    <h1>Editar Artigo</h1>

    <form action="?route=article_update" method="post">
    
        <input type="hidden" name="id" value="<?php echo htmlspecialchars($artigo['id']); ?>">
        <label for="titulo">Título:</label>
        
        <input type="text" id="titulo" name="titulo" value="<?php echo htmlspecialchars($artigo['titulo']); ?>" required>
        <br>
        
        <label for="conteudo">Conteúdo:</label>
        <textarea id="conteudo" name="conteudo" required><?php echo htmlspecialchars($artigo['conteudo']); ?></textarea>
        <br>
        
        <button type="submit">Salvar</button>

    </form>

<a href="?route=article_show&id=<?php echo htmlspecialchars($artigo['id']); ?>">Voltar</a>

3. Controller

ArticleController

A Classe ArticleController, localizada em src/Controller/ArticleController.php, é responsável por gerenciar as operações de CRUD (Criar, Ler, Atualizar e Excluir) relacionadas aos artigos. Este controlador manipula as requisições HTTP, interagindo diretamente com o modelo ArticleModel para executar operações nos dados armazenados na tabela `tbl_artigos`. Além disso, o ArticleController determina qual visão será renderizada com base nas ações realizadas, como exibir uma lista de artigos, apresentar um formulário de criação ou edição, ou confirmar a exclusão de um artigo.

Métodos:

ArticleController.php
        
    namespace App\Controller;

    use App\Model\Article;

    class ArticleController {
        public function create() {
            // Logic for creating an article
        }

        public function read($id) {
            // Logic for reading a specific article
        }

        public function update($id) {
            // Logic for updating an article
        }

        public function delete($id) {
            // Logic for deleting an article
        }

        public function listAll() {
            // Logic for listing all articles
        }
    }
        
    
        
    <?php

    namespace App\Controller;

    use App\Model\Artigo;

    class ArticleController
    {
        public function articles()
        {
            // Logica para exibir a lista de artigos
            $artigos = $this->model->getAll(); // Obtem todos os artigos
            // Aqui você chamaria a view correspondente para exibir os artigos
            // Exemplo: include_once '../src/View/Article/index.php';
            include_once '../src/View/Article/articles.php'; // Inclui a view para exibicao
        }

        public function article($id)
        {
            // Logica para exibir um artigo especifico
            $artigo = $this->model->getById($id);
            // Aqui você chamaria a view correspondente para exibir o artigo
            // Exemplo: include_once '../src/View/Article/show.php';
            include_once '../src/View/Article/article.php';
        }

        public function create() {
            // Logica para exibir o formulario de criacao de artigo
            // Exemplo: include_once '../src/View/Article/create.php';
            //$controller = new ArtigoController();
            //$controller->create(); // Exibe o formulario de criacao de artigo
            include_once '../src/View/Article/create.php';
        }

        public function store()
        {
            // Logica para processar a criaca de um novo artigo
            // Verifique os dados recebidos do formulário e chame $this->model->create($data);
            if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                $titulo = $_POST['titulo'] ?? '';
                $conteudo = $_POST['conteudo'] ?? '';
                $autor = $_POST['autor'] ?? '';
                $this->model->create($titulo, $conteudo, $autor); // Processa a criacao de um novo artigo
                header('Location: ?route=articles');
            } else {
                echo 'Método não permitido.';
            }
        }

        public function edit($id)
        {
            // Logica para exibir o formulario de edicao de um artigo existente
            $artigo = $this->model->getById($id); // Exibe o formulario de edicao de um artigo
            // Exemplo: include_once '../src/View/Article/edit.php';
            include_once '../src/View/Article/edit.php';
        }

        public function update($id, $data)
        {
            // Logica para processar a atualizacao no banco de dados
            // Verifique os dados recebidos do formulário e chame $this->model->update($id, $data);
            $this->model->edit($id, $data); // Processa a atualizacao de um artigo existente
            // Redireciona apos a atualizacao
            header("Location: ?route=article&id=$id");
            exit();
        }

        public function delete($id) {
            // Logica para processar a exclusao de um artigo
            $this->model->delete($id);
            // Redirecionar para a lista de artigos após a exclusão
            header('Location: ?route=articles');
            exit(); // Evita que o script continue após o redirecionamento
        }
        /*
        public function delete()
        {
            $id = $_GET['id'] ?? null;
            if ($id) {
                $this->model->delete($id);
                header('Location: ?route=articles');
            } else {
                echo 'ID do artigo não especificado.';
            }
        }
        */

        private function sanitize(&$data)
        {
            foreach ($data as &$value) {
                $value = htmlspecialchars(strip_tags($value));
            }
        }
    }        
        
    

4. Rotas

routes.php
        
    <?php

    use App\Controller\HomeController;
    use App\Controller\AboutController;
    use App\Controller\PortfolioController;
    use App\Controller\ContactController;
    use App\Controller\ArticleController;
    use App\Controller\ProjectController;
    
    // Definindo as rotas disponiveis
    $routes = [
        'home' => function() {
            $objController = new \App\Controller\HomeController();
            $objController->show();
        },
        'about' => function() {
            $objController = new \App\Controller\AboutController();
            $objController->show();
        },
        'portfolio' => function() {
            $objController = new \App\Controller\PortfolioController();
            $objController->show();
        },
        'contact' => function() {
            $objController = new \App\Controller\ContactController();
            $objController->show();
        },
        'project' => function() {
            $objController = new \App\Controller\ProjectController();
            $objController->show();
        },
        
        // Rotas para os Artigos
        'articles' => function() {
            $objController = new ArticleController();
            $objController->articles(); // Exibe a lista de artigos
        },
        'article_show' => function() {
            $objController = new ArticleController();
            $id = $_GET['id'] ?? null;
            $objController->show($id); // Exibe um artigo especifico
        },
        'article_create' => function() {
            $objController = new ArticleController();
            $objController->create(); // Exibe o formulario de criacao de artigo
        },
        'article_store' => function() {
            $objController = new ArticleController();
            $objController->store(); // Processa a criacao de um novo artigo
        },
        'article' => function() {
            $objController = new ArticleController();
            $id = $_GET['id'] ?? null;
            $objController->article($id); // Exibe o formulario de edicao de um artigo
        },
        'article_update' => function() {
            $objController = new ArticleController();
            $id = $_POST['id'] ?? null;
            $objController->update($id); // Processa a atualizacao de um artigo existente
        },
        'article_delete' => function() {
            $objController = new ArticleController();
            $id = $_POST['id'] ?? null;
            $objController->delete($id); // Processa a exclusao de um artigo
        }
    ];
    
    // Obter o parametro da query string para determinar a rota
    $route = $_GET['route'] ?? 'home'; // Define 'home' como padrao se nenhuma rota for especificada
    
    // Verifica se a rota existe e executa a funcao associada
    if (array_key_exists($route, $routes)) {
        $routes[$route]();
    } else {
        // Pagina 404 personalizada
        http_response_code(404);
        echo "Página não encontrada!";
    }
        
    

Explicação das Rotas:

URLs correspondentes para cada rota:

Essas URLs permitem que o usuário acesse e manipule os artigos da aplicação.

4. Service

Database

Classe responsável pela conexão e interação com o Banco de Dados.

Métodos:

5. Funções Auxiliares

5.1. sanitizeInput($data)

Sanitiza a entrada de dados para remover caracteres indesejados, espaços extras, e escapar caracteres HTML.

Parâmetro:

Retorno:

        
    function sanitizeInput($data) {
        $data = trim($data);
        $data = stripslashes($data);
        $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
        return $data;
    }
        
    
5.2. escapeOutput($data)

Escapa a saída de dados para evitar XSS (Cross-Site Scripting).

Parâmetro:

Retorno:

        
    function escapeOutput($data) {
        return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
    }
        
    

6. Funções Nativas

6.1. htmlspecialchars()

Converte caracteres especiais em entidades HTML para evitar que eles sejam interpretados como código HTML.
htmlspecialchars() - PHP Manual

Parâmetros:

Retorno:


6.2. trim()

Remove os espaços em branco (ou outros caracteres) do início e do fim de uma string.
trim() - PHP Manual

Parâmetro:

Retorno:


6.3. stripslashes()

Remove as barras invertidas de uma string. Utilizada para limpar Strings que foram escapadas com barras invertidas.
stripslashes() - PHP Manual

Parâmetro:

Retorno:


6.4. password_hash()

Cria um hash seguro para a senha usando o algoritmo Bcrypt por padrão.
password_hash() - PHP Manual

Parâmetro:

Retorno:


6.5. password_verify()

Verifica se uma senha corresponde ao hash armazenado.
password_verify() - PHP Manual

Parâmetro:

Retorno:


6.6. PDO

Representa uma conexão entre o PHP e um Banco de Dados.
PDO - PHP Manual

Métodos:


ESTRUTURA DE BANCO DE DADOS

Tabela de artigos: `tbl_artigos`

        
    CREATE TABLE `tbl_artigos` (
        `id_artigo` INT AUTO_INCREMENT PRIMARY KEY,
        `titulo` VARCHAR(255) NOT NULL,
        `conteudo` TEXT NOT NULL,
        `autor` VARCHAR(100) NOT NULL,
        `data_criacao` DATETIME DEFAULT CURRENT_TIMESTAMP,
        `data_atualizacao` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        `status` ENUM('rascunho', 'publicado') DEFAULT 'rascunho'
    ); 
        
    

Descrição dos Campos:

Fluxo de Entrada e Saída de Dados

1. Entrada de Dados (Cadastro de Artigos)

2. Saída de Dados (Visualização de Artigos)

3. Edição de Dados

4. Deleção de Dados

Resumo Geral do Fluxo

1. Sanitização de Entrada de Dados

Para garantir a segurança e a integridade dos dados no CRUD de artigos, é crucial implementar uma sanitização rigorosa. Isso ajuda a prevenir vulnerabilidades como SQL Injection, XSS (Cross-Site Scripting), e outras formas de ataque. Abaixo estão os passos recomendados para uma sanitização de dados robusta:

    
    function sanitizeInput($data) {
        // Remove espaços extras e caracteres indesejados
        $data = trim($data);
        $data = stripslashes($data);
        $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
        return $data;
    }

    // Exemplo de uso:
    $titulo = sanitizeInput($_POST['titulo']);
    $conteudo = sanitizeInput($_POST['conteudo']);
    $autor = sanitizeInput($_POST['autor']);
    $status = in_array($_POST['status'], ['rascunho', 'publicado']) ? $_POST['status'] : 'rascunho';
    

2. Preparação de Consultas SQL (Prepared Statements)

Exemplo em PHP com PDO:

    
    // Conexão segura ao banco de dados usando PDO
    $pdo = new PDO('mysql:host=localhost;dbname=seu_banco_de_dados', 'usuario', 'senha', [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]);

    // Inserção segura de dados
    $stmt = $pdo->prepare("INSERT INTO tbl_artigos (titulo, conteudo, autor, status) VALUES (:titulo, :conteudo, :autor, :status)");
    $stmt->execute([
        ':titulo' => $titulo,
        ':conteudo' => $conteudo,
        ':autor' => $autor,
        ':status' => $status
    ]);
    

3. Validação Adicional do Lado do Servidor

4. Sanitização de Saída de Dados

Exemplo em PHP:

    
    function escapeOutput($data) {
        return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
    }
    
    // Exemplo de uso ao renderizar dados:
    echo escapeOutput($artigo['titulo']);
    echo escapeOutput($artigo['conteudo']);
    

5. Política de Senhas

Exemplo em PHP:

    
    $password = password_hash($senha, PASSWORD_BCRYPT);

    // Para verificar a senha durante o login:
    if (password_verify($senha_digitada, $hash_armazenado)) {
        // Login bem-sucedido
    }
    

6. Proteção Contra CSRF (Cross-Site Request Forgery)

Exemplo em PHP:

    
    // Gerando um token CSRF
    $csrf_token = bin2hex(random_bytes(32));
    $_SESSION['csrf_token'] = $csrf_token;

    // Adicionando o token no formulário
    echo '';

    // Verificando o token na submissão
    if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        die('CSRF token inválido.');
    }
    

7. Logs e Monitoramento

8. Cabeçalhos de Segurança

Essa abordagem de sanitização e validação garante que o sistema esteja bem protegido contra ataques comuns e que os dados manipulados sejam seguros, mantendo a integridade e a confiança no CRUD de artigos.