CRUD Completo com PDO: Create, Read, Update, Delete: Do Básico ao Avançado Já leu

Preparando o Ambiente: Conexão com PDO A PDO (PHP Data Objects) é uma camada de abstração que permite trabalhar com múltiplos bancos de dados usando uma interface uniforme. Antes de implementar o CRUD, você precisa estabelecer uma conexão segura e reutilizável. Crie um arquivo para centralizar a conexão: O atributo garante que erros sejam lançados como exceções, facilitando o tratamento. Guarde credenciais sensíveis em variáveis de ambiente em produção. CREATE: Inserindo Dados no Banco A operação CREATE adiciona novos registros ao banco. Use prepared statements sempre para evitar SQL Injection. Parâmetros nomeados ( ) são mais legíveis que placeholders ( ). O retorna verdadeiro se bem-sucedido. Use se precisar do ID gerado automaticamente. READ: Recuperando e Exibindo Dados Read é a operação mais frequente. Implemente métodos para recuperar um registro específico, todos os registros ou aplicar filtros e paginação. retorna todos os resultados como array; retorna apenas um. retorna associativo (chaves nomeadas); use para objetos. UPDATE: Modificando Registros Existentes Update

Preparando o Ambiente: Conexão com PDO

A PDO (PHP Data Objects) é uma camada de abstração que permite trabalhar com múltiplos bancos de dados usando uma interface uniforme. Antes de implementar o CRUD, você precisa estabelecer uma conexão segura e reutilizável.

Crie um arquivo Database.php para centralizar a conexão:

<?php
class Database {
    private $host = 'localhost';
    private $db = 'loja';
    private $user = 'root';
    private $pass = '';
    private $pdo;

    public function connect() {
        try {
            $this->pdo = new PDO(
                'mysql:host=' . $this->host . ';dbname=' . $this->db,
                $this->user,
                $this->pass,
                [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
            );
            return $this->pdo;
        } catch (PDOException $e) {
            die('Erro na conexão: ' . $e->getMessage());
        }
    }
}
?>

O atributo ERRMODE_EXCEPTION garante que erros sejam lançados como exceções, facilitando o tratamento. Guarde credenciais sensíveis em variáveis de ambiente em produção.

CREATE: Inserindo Dados no Banco

A operação CREATE adiciona novos registros ao banco. Use prepared statements sempre para evitar SQL Injection. Parâmetros nomeados (:nome) são mais legíveis que placeholders (?).

<?php
class Produto {
    private $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function criar($nome, $preco, $estoque) {
        $sql = "INSERT INTO produtos (nome, preco, estoque, criado_em) 
                VALUES (:nome, :preco, :estoque, NOW())";

        $stmt = $this->pdo->prepare($sql);

        return $stmt->execute([
            ':nome' => $nome,
            ':preco' => $preco,
            ':estoque' => $estoque
        ]);
    }
}

// Uso:
$db = new Database();
$pdo = $db->connect();
$produto = new Produto($pdo);

if ($produto->criar('Notebook', 2500.00, 10)) {
    echo "Produto inserido com sucesso!";
}
?>

O execute() retorna verdadeiro se bem-sucedido. Use $this->pdo->lastInsertId() se precisar do ID gerado automaticamente.

READ: Recuperando e Exibindo Dados

Read é a operação mais frequente. Implemente métodos para recuperar um registro específico, todos os registros ou aplicar filtros e paginação.

<?php
public function obterTodos($limit = 10, $offset = 0) {
    $sql = "SELECT * FROM produtos LIMIT :limit OFFSET :offset";
    $stmt = $this->pdo->prepare($sql);

    $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT);
    $stmt->bindValue(':offset', (int)$offset, PDO::PARAM_INT);
    $stmt->execute();

    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

public function obterPorId($id) {
    $sql = "SELECT * FROM produtos WHERE id = :id";
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute([':id' => $id]);

    return $stmt->fetch(PDO::FETCH_ASSOC);
}

public function buscar($termo) {
    $sql = "SELECT * FROM produtos WHERE nome LIKE :termo";
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute([':termo' => "%{$termo}%"]);

    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
?>

fetchAll() retorna todos os resultados como array; fetch() retorna apenas um. PDO::FETCH_ASSOC retorna associativo (chaves nomeadas); use PDO::FETCH_OBJ para objetos.

UPDATE: Modificando Registros Existentes

Update altera dados já presentes no banco. Sempre valide e verifique se o registro existe antes de atualizar para evitar operações silenciosas.

<?php
public function atualizar($id, $nome, $preco, $estoque) {
    $sql = "UPDATE produtos 
            SET nome = :nome, preco = :preco, estoque = :estoque, atualizado_em = NOW()
            WHERE id = :id";

    $stmt = $this->pdo->prepare($sql);
    $resultado = $stmt->execute([
        ':id' => $id,
        ':nome' => $nome,
        ':preco' => $preco,
        ':estoque' => $estoque
    ]);

    return $stmt->rowCount() > 0 ? true : false;
}

public function incrementarEstoque($id, $quantidade) {
    $sql = "UPDATE produtos SET estoque = estoque + :qtd WHERE id = :id";
    $stmt = $this->pdo->prepare($sql);

    return $stmt->execute([
        ':id' => $id,
        ':qtd' => $quantidade
    ]);
}

// Uso:
if ($produto->atualizar(1, 'Notebook Gamer', 3500.00, 5)) {
    echo "Atualizado com sucesso!";
} else {
    echo "Nenhum registro foi modificado.";
}
?>

O método rowCount() informa quantas linhas foram afetadas. Útil para validar se a atualização realmente ocorreu.

DELETE: Removendo Registros

Delete é irreversível. Implemente confirmações, logs ou soft delete (marcar como inativo) em sistemas críticos.

<?php
public function deletar($id) {
    $sql = "DELETE FROM produtos WHERE id = :id";
    $stmt = $this->pdo->prepare($sql);

    return $stmt->execute([':id' => $id]) && $stmt->rowCount() > 0;
}

// Soft delete (recomendado):
public function desativar($id) {
    $sql = "UPDATE produtos SET ativo = 0, deletado_em = NOW() WHERE id = :id";
    $stmt = $this->pdo->prepare($sql);

    return $stmt->execute([':id' => $id]);
}

// Uso em controlador:
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['deletar_id'])) {
    $id = (int)$_POST['deletar_id'];
    if ($produto->deletar($id)) {
        header('Location: /produtos');
    }
}
?>

Soft delete preserva dados para auditoria e recuperação. Sempre valide o ID antes de deletar para evitar exclusões acidentais.

Conclusão

Três pontos essenciais aprendidos: Prepared statements são não-negociáveis para segurança contra SQL Injection; organize o código em classes separando lógica de banco e regras de negócio; valide sempre o número de linhas afetadas para confirmar sucesso real de operações, especialmente em UPDATE e DELETE. Com PDO bem implementada, você tem código seguro, testável e portável entre diferentes bancos de dados.

Referências


Artigos relacionados