Search by

heliomarpm / db-php

heliomarpm

Uma biblioteca leve, de alta performance e sem dependências externas para conexão e manipulação de banco de dados (PDO e MySQLi) em PHP

v1.0.0 2026-10-25 03:44 UTC

This package is auto-updated.

Last update: 2026-10-25 18:46:21 UTC


README

DbPHP

CI Status CodeFactor Packagist Version Packagist Downloads

GitHub Sponsors PayPal Ko-fi Liberapay

DbPHP é uma biblioteca leve, moderna e de alta performance para conexão e manipulação de bancos de dados relacionais em PHP 8.2+.

Oferece suporte unificado a PDO e MySQLi, prepared statements com parâmetros nomeados (:param) e posicionais (?), telemetria nativa de execução, transações atômicas seguras e integração fluida com coleções em memória via linq-php.

🚀 Experimente o Laboratório Interativo Online
Teste cenários reais de consultas, telemetria, transações e SQL livre direto no navegador!

⚡ Destaques

  • Zero Dependências: Construído exclusivamente sobre os módulos nativos do PHP (ext-pdo e ext-mysqli).
  • Parâmetros Nomeados Universais: Use :param tanto com PDO quanto com MySQLi (tradução transparente).
  • Telemetria Integrada: Obtenha o tempo exato de execução da query ($result->elapsedTime) e contagem ($result->count) sem overhead.
  • DTO Imutável QueryResult: Métodos ergonômicos como $result->column('nome'), $result->row, $result->rows e firstOrDefault().
  • Transações Atômicas: Gerenciamento de bloco DB::transaction() com auto-commit e auto-rollback.
  • Ponte com LinqPHP: Encadeie pipelines de transformação em memória chamando ->linq() a partir do resultado da query.

📦 Requisitos

  • PHP 8.2 ou superior
  • Extensões pdo (com drivers como pdo_mysql, pdo_sqlite) e/ou mysqli

📥 Instalação

composer require heliomarpm/db-php

🚀 Guia Prático de Uso

1. Inicialização e Conexão

use HeliomarPM\DbPHP\DB;

// SQLite em memória (ideal para testes, microserviços e serverless):
$db = DB::sqlite();

// SQLite em arquivo persistente:
$db = DB::sqlite("/caminho/para/database.sqlite");

// MySQL via Driver PDO:
$db = DB::mysql(
    database: "minha_base",
    username: "usuario",
    password: "senha_segura",
    hostname: "127.0.0.1",
    port: 3306
);

// MySQL nativo via Driver MySQLi:
$db = DB::connect([
    "driver"   => "mysqli",
    "hostname" => "127.0.0.1",
    "database" => "minha_base",
    "username" => "usuario",
    "password" => "senha_segura",
    "charset"  => "utf8mb4"
]);

2. Consultas (SELECT) e Parâmetros Seguros

2.1 Parâmetros Nomeados (:param) — Recomendado para legibilidade

Você pode usar parâmetros nomeados passando um array associativo com ou sem o prefixo ::

// Busca produtos com preço e estoque mínimos definidos por chave nomeada:
$result = DB::query("
    SELECT id_produto, nome_produto, preco, estoque
    FROM produtos
    WHERE preco >= :min_preco AND estoque >= :min_estoque
    ORDER BY preco DESC
", [
    "min_preco"   => 89.90,
    "min_estoque" => 10,
]);

// O DbPHP aceita tanto ['min_preco' => 89.90] quanto [':min_preco' => 89.90]

2.2 Parâmetros Posicionais (?)

Também é possível usar placeholders posicionais com array indexado:

$result = DB::query("
    SELECT * FROM clientes
    WHERE uf = ? AND vip = ?
", ["SP", 1]);

3. Trabalhando com os Resultados (QueryResult)

O objeto retornado por DB::query() disponibiliza propriedades e métodos ergonômicos:

$result = DB::query("SELECT id_produto, nome_produto, preco FROM produtos");

// 📊 Métricas de Telemetria:
echo $result->count;       // Quantidade de registros retornados (int)
echo $result->elapsedTime; // Tempo de execução em segundos (ex: 0.000185s)

// 📋 Leitura dos Registros:
print_r($result->row);     // Primeira linha como array associativo (ou [] se vazio)
print_r($result->rows);    // Todas as linhas (array de arrays)

// 🎯 Extração Direta de Coluna (elimina array_column):
$nomes = $result->column("nome_produto");
// Retorna: ["PLA Preto", "PETG Branco", "Bico Extrusor", ...]

// 🔍 Localização com Condição (Early-Exit):
$produtoBarato = $result->firstOrDefault(fn($p) => (float)$p["preco"] < 50.00);

// 🔁 Iteração Direta (QueryResult implementa IteratorAggregate):
foreach ($result as $linha) {
    echo "{$linha['nome_produto']} - R$ {$linha['preco']}\n";
}

4. Operações de Escrita (INSERT, UPDATE, DELETE)

Utilize DB::execute() para operações que modificam dados. Ele retorna o número de linhas afetadas:

4.1 Inserção e Obtenção do ID Gerado

$afetados = DB::execute("
    INSERT INTO clientes (nome_cliente, uf, cidade, vip, saldo_credito)
    VALUES (:nome, :uf, :cidade, :vip, :saldo)
", [
    "nome"   => "Mariana Silva",
    "uf"     => "MG",
    "cidade" => "Belo Horizonte",
    "vip"    => 1,
    "saldo"  => 250.00
]);

$novoId = DB::lastInsertId(); // ID autonumérico inserido (ex: 9)

4.2 Atualização com Parâmetros Nomeados

$reajustados = DB::execute("
    UPDATE produtos
    SET preco = preco * :fator
    WHERE id_categoria = :categoria AND estoque > :min_estoque
", [
    "fator"       => 1.10, // Reajuste de 10%
    "categoria"   => 1,
    "min_estoque" => 0,
]);

echo "Total de produtos atualizados: {$reajustados}";

4.3 Exclusão Controlada

$removidos = DB::execute("
    DELETE FROM pedidos
    WHERE status = :status AND data_pedido < :limite
", [
    "status" => "cancelado",
    "limite" => "2026-01-01 00:00:00",
]);

5. Transações Atômicas Seguras (DB::transaction)

O método DB::transaction() encapsula a execução em um bloco com auto-commit e auto-rollback. Se qualquer exceção for lançada dentro da closure, a transação é revertida imediatamente:

// Exemplo: Transferência bancária atômica que retorna o protocolo da operação
$protocolo = DB::transaction(function ($driver) {
    // 1. Debita da conta de origem:
    $driver->execute("
        UPDATE contas
        SET saldo = saldo - :valor
        WHERE id_conta = :origem AND saldo >= :valor
    ", [
        "valor"  => 500.00,
        "origem" => 1,
    ]);

    // 2. Credita na conta de destino:
    $driver->execute("
        UPDATE contas
        SET saldo = saldo + :valor
        WHERE id_conta = :destino
    ", [
        "valor"   => 500.00,
        "destino" => 2,
    ]);

    // 3. Registra comprovante:
    $driver->execute("
        INSERT INTO transferencias (conta_origem, conta_destino, valor, data_hora)
        VALUES (:origem, :destino, :valor, datetime('now'))
    ", [
        "origem"  => 1,
        "destino" => 2,
        "valor"   => 500.00,
    ]);

    return $driver->lastInsertId();
});

echo "Transferência confirmada com ID: {$protocolo}";

6. Poder Combinado: DbPHP + LinqPHP

Se você tiver a biblioteca parceira heliomarpm/linq-php instalada, você pode encadear métodos LINQ diretamente do resultado da consulta SQL:

$destaques = DB::query("
    SELECT p.id_produto, p.nome_produto, c.nome_categoria, p.preco, p.estoque
    FROM produtos p
    INNER JOIN categorias c ON c.id_categoria = p.id_categoria
")
->linq()
->where(fn($p) => (float)$p["preco"] > 50.00)
->orderByKey("preco", descending: true)
->select([
    "id_produto"     => "Código",
    "nome_produto"   => "Produto",
    "nome_categoria" => "Categoria",
    "preco"          => "Preço",
])
->take(5)
->toArray();

7. Paginação Nativa com DB::paginate()

O método DB::paginate() calcula automaticamente o COUNT(*) total da consulta, injeta de forma segura as cláusulas LIMIT e OFFSET e retorna um DTO imutável e estruturado (PaginatedResult):

$paginado = DB::paginate(
    sql: "SELECT * FROM produtos WHERE preco >= :preco ORDER BY id_produto DESC",
    params: ["preco" => 50.00],
    page: 1,
    perPage: 15
);

// 📋 Dados da Página Atual:
$itens = $paginado->items; // Array de linhas da página (ou iteração via foreach)

// 📊 Metadados de Paginação:
echo $paginado->total;            // Total geral de registros encontrados (ex: 45)
echo $paginado->currentPage;      // Página atual: 1
echo $paginado->lastPage;         // Total de páginas calculadas: 3
echo $paginado->perPage;          // Itens por página: 15
echo $paginado->from;             // Índice inicial: 1
echo $paginado->to;               // Índice final: 15
echo $paginado->hasMorePages;     // true se houver próxima página
echo $paginado->hasPreviousPages; // true se houver página anterior
echo $paginado->elapsedTime;      // Tempo total somado (contagem + consulta)

// ⚡ Serialização JSON direta para APIs REST:
header('Content-Type: application/json');
echo json_encode($paginado);

Resposta JSON gerada automaticamente:

{
  "data": [
    { "id_produto": 110, "nome_produto": "Impressora 3D", "preco": 3450.00 }
  ],
  "pagination": {
    "total": 45,
    "per_page": 15,
    "current_page": 1,
    "last_page": 3,
    "from": 1,
    "to": 15,
    "has_more": true,
    "has_previous": false
  },
  "elapsed_time": 0.000325
}

🖥️ Laboratório Interativo Local

Você pode iniciar o servidor de demonstração interativo com todas as tabelas e cenários pré-configurados com um único comando:

composer start

Em seguida, abra http://localhost:8000 no navegador para explorar as métricas de telemetria, testar transações e rodar consultas SQL em tempo real.

🧪 Qualidade de Código e Testes

O projeto segue rigorosos padrões de tipagem estrita e cobertura de testes:

# Rodar todos os testes unitários (PHPUnit 100% verde)
composer test

# Análise estática de tipos (PHPStan no Nível 8 mais rigoroso)
composer lint

# Validação e formatação de código (Laravel Pint)
composer format
composer format:fix
composer format:full

# Verificação completa da suíte
composer check

🤝 Contribuições e suporte

Existem várias formas de contribuir:

  • ⭐ Marcar o repositório com uma estrela
  • 🐞 Relatar bugs
  • 💡 Sugerir funcionalidades ou novos drivers
  • 🧾 Melhorar a documentação
  • 📢 Compartilhar o projeto

Para propor uma melhoria ou contribuição, veja o Guia de Contribuição.
Se precisar de ajuda ou encontrou um problema, consulte o Suporte ou abra uma Issue. Leia também o Código de Conduta.

Obrigado a todos que já contribuíram:

Contribuidores

Criado com contrib.nn

💵 Apoie o Projeto

Se você gosta do projeto, considere fazer uma doação ao desenvolvedor via GitHub Sponsors, Ko-fi, PayPal ou Liberapay — a escolha é sua. 😉

GitHub Sponsors PayPal Ko-fi Liberapay

📝 Licença

Distribuído sob a licença MIT © Heliomar P. Marques.
Sinta-se livre para utilizar, customizar e estender estas bibliotecas nos seus ambientes de desenvolvimento. 🔝