Parte 05

CRUD de pacientes

Um mini-sistema de hospital: cadastrar, listar, editar e remover pacientes com 5 características. Tudo com PDO + prepared statements — o caminho seguro e recomendado.

⚠️ Por que prepared statement? A query vai com ? no lugar dos valores, e os dados são passados separados no execute(). O banco trata tudo como dado, nunca como comando — isso elimina SQL injection. Jamais concatene variável dentro da query (ex.: "... WHERE id = $id").
1

Criar a tabela

Primeiro a estrutura no banco. O id é a chave primária que se autoincrementa; as outras 5 colunas são as características do paciente. Rode isto uma vez no phpMyAdmin.

pacientes.sql
CREATE TABLE pacientes (
    id           INT AUTO_INCREMENT PRIMARY KEY,
    nome         VARCHAR(100) NOT NULL,   -- 1
    idade        INT NOT NULL,            -- 2
    telefone     VARCHAR(20),             -- 3
    sintoma      VARCHAR(100),            -- 4
    data_entrada DATE                     -- 5
);
2

Conectar ao banco (PDO)

A conexão fica num arquivo separado (conexao.php) para reaproveitar. Sempre dentro de try/catch e com o modo de exceção ligado, para os erros não passarem em branco.

conexao.php
<?php
$dsn = "mysql:host=localhost;dbname=hospital;charset=utf8mb4";

try {
    $pdo = new PDO($dsn, "root", "");

    // Erros viram exceções (essencial para o try/catch agir).
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // fetch() devolve array associativo por padrão.
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

} catch (PDOException $e) {
    exit("Não foi possível conectar ao banco.");
}
3

Adicionar paciente (INSERT)

Cinco ? na query, cinco valores no execute(), na mesma ordem. Depois de inserir, lastInsertId() devolve o id que o banco gerou.

adicionar.php
<?php
require "conexao.php";

$sql = "INSERT INTO pacientes (nome, idade, telefone, sintoma, data_entrada)
        VALUES (?, ?, ?, ?, ?)";

$stmt = $pdo->prepare($sql);
$stmt->execute(["Ana Lima", 34, "11999998888", "Febre", "2026-06-01"]);

echo "Paciente cadastrado! ID: " . $pdo->lastInsertId();
// Paciente cadastrado! ID: 1
4

Listar pacientes (SELECT)

Para ler, use SELECT e percorra o resultado com foreach. Como não há valor do usuário na query, aqui pode usar query() direto. Toda saída no HTML é escapada com h().

listar.php
<?php
require "conexao.php";

// Helper anti-XSS: escapa tudo que vai para o HTML.
function h(string $s): string {
    return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
}

$pacientes = $pdo->query("SELECT * FROM pacientes ORDER BY nome")->fetchAll();

foreach ($pacientes as $p) {
    echo h($p["nome"]) . ", " . $p["idade"] . " anos";
    echo " — " . h($p["sintoma"]) . "\n";
}
// Saída: Ana Lima, 34 anos — Febre
5

Editar paciente (UPDATE)

O UPDATE também usa ? — inclusive no WHERE id = ?, que nunca pode faltar (senão altera todos). rowCount() diz quantas linhas foram afetadas.

editar.php
<?php
require "conexao.php";

$sql = "UPDATE pacientes SET sintoma = ?, data_entrada = ? WHERE id = ?";

$stmt = $pdo->prepare($sql);
$stmt->execute(["Tosse", "2026-06-02", 1]);

echo $stmt->rowCount() . " paciente atualizado";
// 1 paciente atualizado
6

Remover paciente (DELETE)

Mesma ideia: DELETE com WHERE id = ? e o id ligado como parâmetro. Por segurança, faça o cast (int) quando o id vier da URL.

remover.php
<?php
require "conexao.php";

$id = (int) ($_GET["id"] ?? 0);   // cast protege contra lixo na URL

$stmt = $pdo->prepare("DELETE FROM pacientes WHERE id = ?");
$stmt->execute([$id]);

echo "Paciente removido";
// Paciente removido
📌 Resumo do CRUD: Create = INSERT, Read = SELECT, Update = UPDATE, Delete = DELETE. Os quatro sempre com prepare() + execute() quando há valor de fora.
7

Tudo junto: a página completa

Agora os 6 passos num arquivo só, com o HTML do formulário e da listagem. O mesmo formulário cria e edita (o id escondido decide qual). Após salvar, faz POST-Redirect-GET (redireciona para não reenviar no F5) com um ?msg= que vira uma mensagem de aviso (via match). A tabela mostra todas as colunas e há um CSS mínimo no <head>. Toda saída passa por h().

pacientes.php
<?php
require "conexao.php";   // traz o $pdo já configurado

function h(string $s): string {
    return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
}

// Converte a data do banco (YYYY-MM-DD) para BR (DD/MM/AAAA); vazia/NULL vira "—".
function dataBr(?string $data): string {
    if ($data === null || $data === "" || $data === "0000-00-00") {
        return "—";
    }
    return (new DateTime($data))->format("d/m/Y");
}

// ---- CRIAR ou ATUALIZAR (POST) ----
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $id       = (int) ($_POST["id"] ?? 0);
    $nome     = trim($_POST["nome"] ?? "");
    $idade    = (int) ($_POST["idade"] ?? 0);
    $telefone = trim($_POST["telefone"] ?? "");
    $sintoma  = trim($_POST["sintoma"] ?? "");
    // Armadilha: data vazia numa coluna DATE vira 0000-00-00. Por isso vazio = NULL.
    $entrada  = trim($_POST["data_entrada"] ?? "");
    $entrada  = $entrada !== "" ? $entrada : null;

    if ($nome !== "") {
        if ($id > 0) {
            // Editar existente.
            $stmt = $pdo->prepare("UPDATE pacientes SET nome=?, idade=?, telefone=?, sintoma=?, data_entrada=? WHERE id=?");
            $stmt->execute([$nome, $idade, $telefone, $sintoma, $entrada, $id]);
        } else {
            // Inserir novo.
            $stmt = $pdo->prepare("INSERT INTO pacientes (nome, idade, telefone, sintoma, data_entrada) VALUES (?, ?, ?, ?, ?)");
            $stmt->execute([$nome, $idade, $telefone, $sintoma, $entrada]);
        }
    }
    header("Location: pacientes.php?msg=salvo");   // POST-Redirect-GET + aviso
    exit;
}

// ---- EXCLUIR (GET ?excluir=ID) ----
if (isset($_GET["excluir"])) {
    $stmt = $pdo->prepare("DELETE FROM pacientes WHERE id = ?");
    $stmt->execute([(int) $_GET["excluir"]]);
    header("Location: pacientes.php?msg=removido");
    exit;
}

// ---- EDITAR: carregar o paciente no formulário (GET ?editar=ID) ----
$edicao = null;
if (isset($_GET["editar"])) {
    $stmt = $pdo->prepare("SELECT * FROM pacientes WHERE id = ?");
    $stmt->execute([(int) $_GET["editar"]]);
    $edicao = $stmt->fetch();
}

// ---- LISTAR ----
$pacientes = $pdo->query("SELECT * FROM pacientes ORDER BY nome")->fetchAll();

// Mensagem de feedback, conforme o ?msg=... que veio do redirect.
$aviso = match ($_GET["msg"] ?? "") {
    "salvo"    => "Paciente salvo!",
    "removido" => "Paciente removido!",
    default    => "",
};
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="utf-8">
    <style>
        body  { font-family: sans-serif; max-width: 640px; margin: 30px auto; }
        input, button { padding: 6px; margin: 2px 0; }
        table { width: 100%; border-collapse: collapse; margin-top: 16px; }
        th, td { border: 1px solid #ccc; padding: 6px 10px; text-align: left; }
        .aviso { background: #e7f9ec; color: #1c7c3a; padding: 8px 12px; border-radius: 6px; }
    </style>
</head>
<body>
    <h1>Pacientes</h1>

    <!-- Aparece só quando há mensagem -->
    <?php if ($aviso !== ""): ?>
        <p class="aviso"><?= h($aviso) ?></p>
    <?php endif; ?>

    <!-- O mesmo form cria E edita (o id escondido decide) -->
    <form method="post">
        <input type="hidden" name="id"           value="<?= h($edicao["id"] ?? "") ?>">
        <input type="text"   name="nome"         value="<?= h($edicao["nome"] ?? "") ?>" placeholder="Nome">
        <input type="number" name="idade"        value="<?= h($edicao["idade"] ?? "") ?>" placeholder="Idade">
        <input type="text"   name="telefone"     value="<?= h($edicao["telefone"] ?? "") ?>" placeholder="Telefone">
        <input type="text"   name="sintoma"      value="<?= h($edicao["sintoma"] ?? "") ?>" placeholder="Sintoma">
        <input type="date"   name="data_entrada" value="<?= h($edicao["data_entrada"] ?? "") ?>">
        <button type="submit"><?= $edicao ? "Salvar" : "Adicionar" ?></button>
    </form>

    <table>
        <tr><th>Nome</th><th>Idade</th><th>Telefone</th><th>Entrada</th><th>Sintoma</th><th>Ações</th></tr>
    <?php foreach ($pacientes as $p): ?>
        <tr>
            <td><?= h($p["nome"]) ?></td>
            <td><?= h($p["idade"]) ?></td>
            <td><?= h($p["telefone"]) ?></td>
            <td><?= dataBr($p["data_entrada"]) ?></td>
            <td><?= h($p["sintoma"]) ?></td>
            <td>
                <a href="?editar=<?= (int) $p["id"] ?>">editar</a>
                <a href="?excluir=<?= (int) $p["id"] ?>"
                   onclick="return confirm('Excluir?')">excluir</a>
            </td>
        </tr>
    <?php endforeach; ?>
    </table>
</body>
</html>
📌 Como rodar: crie a tabela (passo 1) no phpMyAdmin, salve conexao.php e pacientes.php em htdocs/ e acesse http://localhost/pacientes.php pelo Apache. Como usa header(), precisa rodar no servidor — não abra como file://.
← Parte 4 · APIs & projetos Voltar à capa →