(PHP, DataTables e Bootstrap) Formulário para consulta em banco de dados e apresentação dos dados em tabela
Tags: php, bootstrap, datatable, database
Published: 2023-10-27 01:14:24

Neste artigo aprenderemos de maneira prática e eficaz a realizar consultas em um banco de dados através de um formulário e retornar o resultado dessa consulta em forma de tabela em nossa página web.

**Minha ideia aqui é utilizar o PHP puro,** mas existem frameworks que podem te auxiliar e tornam essa execução bem simples, como por exemplo o **Laravel e o Filament**, porém dessa forma você precisará de um conhecimento mais avançado na linguagem.

Para executarmos nosso plano, aqui utilizaremos somente o **PHP** puro como base, a extensão **PDO** nativa do PHP para conexão com o banco de dados, os frameworks **Bootstrap** para nos auxiliar no front-end do formulário, **DataTables** para nos auxiliar com a tabela e **JQuery** pois é um requisito do DataTables.

Bom primeiramente, é necessário que você possua um banco de dados com uma tabela populada para que possamos realizar a consulta, neste tutorial irei utilizar uma tabela em um banco MySQL, mas o tipo de banco fica ao seu critério.

Minha tabela no banco de dados contém as seguintes colunas:

> id | nome | cpf | cargo | telefone | sexo

Disponibilizei o **código .sql desse DB** de teste no repositório no GitHub que você pode acessar através do link disponibilizado no final desse artigo.

A minha intenção é criar um formulário com os campos de consulta “nome”, “cargo” e “sexo” para apresentar os demais dados na tabela, sendo que você pode preencher um, dois, todos ou nenhum dos campos para realizar a pesquisa.

Primeiramente, vamos criar uma página com nome consulta.php contendo apenas o escopo do HTML:5 e importação dos frameworks para nosso projeto, irei fazer isso através dos CDNs.

> **Bootstrap:**
> https://getbootstrap.com/docs/
> **JQuery:**
> https://releases.jquery.com/
> **DataTables:**
> https://datatables.net/download/

**OBS:** O DataTables possui várias extensões para você personalizar sua tabela, porém a mais interessante e que iremos utilizar aqui é a extensão _Buttons_ que nos permite fazer o download da tabela em PDF e Excel.

**Após adicionar os CDNs,** inicialmente nossa página _consulta.php_ irá ficar basicamente dessa maneira:

```
<!doctype html>
<html lang="pt-br">
  <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Sistema de Consultas</title>

  <!-- CSS Bootstrap -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">

  <!-- CSS DataTables -->
  <link href="https://cdn.datatables.net/v/bs5/jszip-3.10.1/dt-1.13.6/b-2.4.2/b-colvis-2.4.2/b-html5-2.4.2/b-print-2.4.2/datatables.min.css" rel="stylesheet">
  </head>
  <body>
<main>

</main>
  <!-- JS JQuery -->
  <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
  
  <!-- JS Bootstrap -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>

  <!-- JS DataTables -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script>
  <script src="https://cdn.datatables.net/v/bs5/jszip-3.10.1/dt-1.13.6/b-2.4.2/b-colvis-2.4.2/b-html5-2.4.2/b-print-2.4.2/datatables.min.js"></script>
</body>
</html>
```

Agora, nós iremos criar um arquivo chamado _database.php_ para criarmos nossa classe de **conexão com o banco de dados**, neste arquivo deve conter o seguinte script:

```
<?php

class Database {
  private $connection;
  private static $_instance;
  private $dbhost = 'db_host';
  private $dbuser = 'db_login';
  private $dbpass = 'db_pass';
  private $dbname = 'db_name';

  /*
      * Pega a instancia do banco de dados
      * @return Instance
  */
  public static function getInstance()
    {
        if (! self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    // Construtor
    private function __construct()
    {
        try {
            $this->connection = new PDO('mysql:host=' . $this->dbhost . ';dbname=' . $this->dbname . ';charset=utf8', $this->dbuser, $this->dbpass);
            $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            // Error handling
        } catch (PDOException $e) {
            die("Falha ao conectar ao banco de dados: " . $e->getMessage());
        }
    }

    // Método mágico previne conexão duplicada
    private function __clone()
    {}

    // Realiza a conexão
    public function getConnection()
    {
        return $this->connection;
    }
}
```
**OBS:** Modifique as variáveis com as informações do seu banco de dados para que a conexão seja realizada sem problemas.

Após a criação do arquivo de configuração do banco de dados, iremos adicionar esse arquivo em nossa página _consulta.php_, no início do código, **acima de tudo**, adicione esse script:

```
<?php
  require_once 'database.php';
?>
```
Adicionaremos nosso formulário em nossa página _consulta.php_, o formulário deve estar **dentro da tag main**, o código é o seguinte:

```
<form action="" method="post">
  <div class="row">
    <div class="col-md-12 my-1">
      <label for="nome">Nome:</label>
      <!-- Input para preencher o nome -->
      <input type="text" id="nome" name="nome" class="form-control" placeholder="Digite o nome" value="<?= $_POST["nome"] ?>"></input>
    </div>
    <div class="col-md-6 my-1">
      <label for="sexo">Sexo:</label>
      <select id="sexo" name="sexo" class="form-control">
        <option disabled selected>Selecione</option>
        <?php
          // Array de opções do select, ele irá relembrar a opção selecionada após o submit do form
          $values = array('F' => 'Feminino', 'M' => 'Masculino');
          foreach($values as $val => $value) {
            $selected = (!empty($_POST['sexo']) && $_POST['sexo'] == $val) ? 'selected' : '';
            echo "<option value='$val' $selected>$value</option>";
          }
        ?>
      </select>
    </div>
    <div class="col-md-6 my-1">
      <label for="cargo">Cargo:</label>
      <select id="cargo" name="cargo" class="form-control">
        <option disabled selected>Selecione</option>
        <?php
          // Array de opções do select, ele irá relembrar a opção selecionada após o submit do form
          $values = array('Presidente' => 'Presidente', 'Gerente' => 'Gerente', 'Funcionário' => 'Funcionário');
          foreach($values as $val => $value) {
            $selected = (!empty($_POST['cargo']) && $_POST['cargo'] == $val) ? 'selected' : '';
            echo "<option value='$val' $selected>$value</option>";
          }
        ?>
      </select>
    </div>
    <div class="col-md-12 my-2">
      <button type="submit" name="submit" class="btn btn-primary">Pesquisar</button>
    </div>
  </div>
</form>
```
Logo após o formulário iremos adicionar um **código PHP para que o resultado da tabela** seja apresentado somente após o envio do formulário, o código é o seguinte:

```
<?php if (isset($_POST["submit"])) { ?>

<?php } ?>
```
Neste momento iremos de fato adicionar as validações e o script que **pegará os dados do formulário e realizará a consulta no banco de dados**, o código deve ficar logo após a verificação do envio do formulário, ficando assim:
```
<?php if (isset($_POST["submit"])) { 

// Faz as validações dos inputs e emite as querys
// Essa validação nos permitirá que os campos do form não sejam obrigatórios
if (!empty($_POST["nome"])) {
  $nomeQuery = "nome LIKE '%{$_POST["nome"]}%' COLLATE utf8_general_ci";
} else {
  $nomeQuery = "nome IS NOT NULL";
}

if (!empty($_POST["sexo"])) {
  $sexoQuery = " AND sexo LIKE '%{$_POST["sexo"]}%'";
} else {
  $sexoQuery = " AND sexo IS NOT NULL";
}

if (!empty($_POST["cargo"])) {
  $cargoQuery = " AND cargo LIKE '%{$_POST["cargo"]}%'";
} else {
  $cargoQuery = " AND cargo IS NOT NULL";
}

// Realiza a busca das informações no banco de dados
try {
  $db = Database::getInstance();
  $con = $db->getConnection();
  // Query de busca no banco de dados
  $query = "SELECT * FROM db_teste.tb_teste WHERE " . $nomeQuery . $sexoQuery . $cargoQuery;
  $stmt = $con->prepare($query);
  $stmt->execute();
  $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOexception $error) {
  // echo $query . "<br>";
  die("Erro ao retornar os dados: " . $error->getMessage());
}
  
?>

<?php } ?>
```
O _COLLATE utf8_general_ci_ adicionado na query do nome tem a função de ignorar a edição do caracteres, como por exemplo acentos ou letras maiúsculas ou minúsculas na hora da pesquisa do input.

**OBS:** É importante ressaltar que o tipo de COLLATE muda de acordo com o tipo de banco de dados, portanto fique atento.

Após isso, iremos fazer o código da nossa **tabela que mostrará os resultados**, esse código deve estar entre a _tag php acima_, minha tabela ficou assim:
```
<div class="row my-4">
  <div class="col table-responsive">
    <!-- O id da table corresponde ao id setado no código do DataTables -->
    <table id="resultado" class="table table-sm table-bordered table-striped table-hover mt-4 mb-4">
      <thead>
        <tr>
          <th scope="col">Nome</th>
          <th scope="col">CPF</th>
          <th scope="col">Cargo</th>
          <th scope="col">Sexo</th>
          <th scope="col">Telefone</th>
        </tr>
      </thead>
      <tbody>
      <?php
        // Irá buscar os resultados do banco de dados através da variável $result
        foreach ($result as $row) {
          echo "<tr>";
          echo "<td>" . $row['nome'] . "</td>";
          echo "<td>" . $row['cpf'] . "</td>";
          echo "<td>" . $row['cargo'] . "</td>";
          echo "<td>" . $row['sexo'] . "</td>";
          echo "<td>" . $row['telefone'] . "</td>";
          echo "</tr>";
        }
      ?>
      </tbody>
    </table>
  </div>  
</div>
```
Por fim, iremos adicionar o código do DataTables para a modificação da nossa tabela, esse código deve ser adicionado no **final da nossa página** antes de fechar a tag body, o código é este:

```
<script>
  $(document).ready(function() {
    $('#resultado').DataTable({
      // Ordenação da tabela pela coluna (0 = primeira coluna)
      order: [[0, 'asc']],
      // Quantidade de resultados a serem apresentados por página
      "iDisplayLength": 25,
      // Organização do layout da tabela
      dom: "<'row'<'col-sm-4'B><'col-sm-4 text-center'l><'col-sm-4'f>>" +
            "<'row'<'col-sm-12'tr>>" +
            "<'row'<'col-sm-6'i><'col-sm-6'p>>",
      buttons: [
        {
          // Botão para download da tabela em Excel
          extend: 'excelHtml5',
          orientation: 'landscape',
          className: 'btn btn-sm btn-success',
          messageTop: 'Resultado dos Dados da Consulta'
        },
        {
          // Botão para download da tabela em PDF
          extend: 'pdfHtml5',
          orientation: 'landscape',
          className: 'btn btn-sm btn-primary',
          messageTop: 'Resultado dos Dados da Consulta'
        }
      ]
    });
  });
</script>
```
Pronto, finalmente nosso código está finalizado e funcional, o resultado deve ficar assim:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxq5bt9bxvsdy5qs5dit.png)

É importante ressaltar que eu fiz esse código de uma maneira bem simplificada, mas você pode aprimorar essa ideia da maneira que for mais conveniente para ti. De qualquer forma estarei disponibilizando esse código completo em um **repositório no GitHub** que você pode acessar através do link abaixo:

[https://github.com/matsesso/consulta-php-datatables](https://github.com/matsesso/consulta-php-datatables)

É isso, espero ter ajudado, tentei explicar de uma forma detalhada e deixei os códigos bem comentados para que todos possam entender, recomendo que visitem e estudem as documentações das tecnologias utilizadas neste artigo.