storage 3. Conexão Segura com Banco de Dados
A conexão com o banco de dados é o coração da sua aplicação. É aqui que os dados do usuário, transações e toda a informação crítica do sistema residem. Uma conexão mal configurada pode expor sua aplicação a SQL Injection, vazamento de credenciais e perda total de dados.
O PDO (PHP Data Objects) é a biblioteca padrão moderna do PHP para comunicação com bancos de dados.
Diferente das antigas funções mysql_* (descontinuadas), o PDO oferece
prepared statements, proteção contra injection e suporte a múltiplos bancos (MySQL, PostgreSQL, SQLite).
Nesta seção, você aprenderá a criar uma conexão robusta, com tratamento de erros adequado, prepared statements para prevenir ataques e boas práticas que são exigidas em ambientes profissionais.
$query = "SELECT * FROM users WHERE id = $id".
Isto permite SQL Injection e pode destruir seu banco de dados.
vpn_key Por Que PDO e Prepared Statements?
Proteção SQL Injection
Prepared statements separam a lógica SQL dos dados. O banco nunca interpreta dados do usuário como comandos.
Portabilidade
Trocar de MySQL para PostgreSQL? Apenas mude o DSN. O código permanece o mesmo.
Performance
O banco compila a query uma vez e reutiliza o plano de execução, tornando queries repetidas mais rápidas.
code Criando a Conexão PDO Segura
📁 config/database.php - Conexão com Tratamento de Erros
PDO::ERRMODE_EXCEPTION, // Lança exceções em erros
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Array associativo
PDO::ATTR_EMULATE_PREPARES => false, // Prepared statements nativos
PDO::ATTR_PERSISTENT => false, // Não usar conexões persistentes
];
// 4. Tentar conexão com tratamento de erro
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, $options);
// Log de sucesso (remover em produção)
// error_log("✅ Conexão PDO estabelecida com sucesso");
} catch (PDOException $e) {
// NUNCA exibir detalhes do erro para o usuário final!
error_log("❌ Erro PDO: " . $e->getMessage());
// Retornar erro genérico
http_response_code(500);
echo json_encode([
'success' => false,
'message' => 'Erro ao conectar com o banco de dados'
]);
exit;
}
// Agora $pdo está disponível em toda a aplicação
?>
.env)
para armazenar credenciais. Nunca commite senhas no Git. Use bibliotecas como
vlucas/phpdotenv para carregar .env.
security Prepared Statements: A Proteção Definitiva
❌ Código Vulnerável (NUNCA use isto)
// ❌ VULNERÁVEL A SQL INJECTION $id = $_GET['id']; // Pode ser: "1 OR 1=1" $query = "SELECT * FROM users WHERE id = $id"; $result = $pdo->query($query); // Um atacante pode enviar: ?id=1 OR 1=1 // Query executada: SELECT * FROM users WHERE id = 1 OR 1=1 // Resultado: TODOS os usuários vazados!
✅ Código Seguro com Prepared Statements
// ✅ SEGURO - Prepared Statement
$id = $_GET['id'];
// 1. Preparar query com placeholder (?)
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
// 2. Executar com binding de parâmetros
$stmt->execute([$id]);
// 3. Buscar resultado
$user = $stmt->fetch();
// Agora, mesmo que $id seja "1 OR 1=1", o banco trata como string literal
// Query real: SELECT * FROM users WHERE id = '1 OR 1=1'
// Resultado: Nenhum usuário (id não existe), sistema protegido!
build Métodos Principais do PDO
arrow_forward prepare() + execute()
// Para queries que precisam de dados externos
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
$user = $stmt->fetch();
playlist_add query()
// Apenas para queries estáticas (sem dados externos)
$stmt = $pdo->query('SELECT * FROM categories');
$categories = $stmt->fetchAll();
add_circle lastInsertId()
// Pegar ID do último INSERT
$stmt = $pdo->prepare('INSERT INTO users (name) VALUES (?)');
$stmt->execute(['João']);
$newId = $pdo->lastInsertId();
format_list_numbered rowCount()
// Contar linhas afetadas (UPDATE/DELETE)
$stmt = $pdo->prepare('DELETE FROM logs WHERE created_at < ?');
$stmt->execute(['2024-01-01']);
$deleted = $stmt->rowCount();
error_outline Tratamento de Erros Profissional
// api/users/get-user.php
prepare('SELECT id, name, email FROM users WHERE id = ?');
$stmt->execute([$id]);
$user = $stmt->fetch();
if (!$user) {
http_response_code(404);
echo json_encode(['success' => false, 'message' => 'Usuário não encontrado']);
exit;
}
echo json_encode(['success' => true, 'data' => $user]);
} catch (PDOException $e) {
// Log detalhado no servidor
error_log("Erro PDO: " . $e->getMessage());
// Resposta genérica para o cliente
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Erro ao buscar usuário']);
} catch (InvalidArgumentException $e) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
?>
- Log detalhado no servidor (
error_log()) - Mensagem genérica para o usuário
- HTTP status codes corretos (400, 404, 500)
- Never leak sensitive information