Banco de Dados no Módulo
Como configurar conexões, criar migrations e seeders no seu módulo.
Conexão de Banco de Dados Personalizada (Obrigatória)
Para criar projetos na IDE, você deve configurar uma conexão de banco de dados personalizada. Isso garante isolamento total dos seus dados de desenvolvimento.
Você não pode criar projetos sem antes configurar uma conexão de banco de dados. O sistema bloqueará a criação com a mensagem: "Você precisa configurar uma conexão de banco de dados antes de criar um projeto".
Por que é obrigatório?
Isolamento Total
Seus módulos não compartilham o banco com o sistema core. Dados de desenvolvimento ficam completamente separados.
Flexibilidade
Use PostgreSQL ou MySQL. Conecte-se a bancos locais ou em nuvem (Aiven, AWS RDS, etc.).
Segurança
Credenciais criptografadas com AES-256-CBC. Suporte a SSL/TLS com certificados CA.
Arquivo connection.php
Quando você cria um módulo na IDE, o arquivo Database/connection.php é gerado automaticamente com o valor 'auto':
<?php
// Gerado automaticamente pela IDE
// Sempre retorna 'auto' para usar sua conexão personalizada
return 'auto';
O valor 'auto' faz com que o sistema use automaticamente sua conexão personalizada. Como a conexão personalizada é obrigatória, este arquivo sempre terá o mesmo valor.
Migrations
Migrations criam e removem tabelas. Devem ter funções up e down e verificar o driver do banco:
<?php
use PDO;
return [
'up' => function (PDO $pdo): void {
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
if ($driver === 'pgsql') {
$pdo->exec("CREATE TABLE IF NOT EXISTS produtos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
nome VARCHAR(255) NOT NULL,
preco DECIMAL(10,2) NOT NULL DEFAULT 0,
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
)");
} else {
$pdo->exec("CREATE TABLE IF NOT EXISTS produtos (
id CHAR(36) PRIMARY KEY,
nome VARCHAR(255) NOT NULL,
preco DECIMAL(10,2) NOT NULL DEFAULT 0,
criado_em DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
}
},
'down' => function (PDO $pdo): void {
$pdo->exec("DROP TABLE IF EXISTS produtos");
},
];
Seeders
Seeders inserem dados iniciais. Devem ser executados manualmente após as migrations:
<?php
use PDO;
return function (PDO $pdo): void {
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
$id = $driver === 'pgsql'
? $pdo->query('SELECT gen_random_uuid()')->fetchColumn()
: bin2hex(random_bytes(16));
$pdo->prepare("INSERT INTO produtos (id, nome, preco) VALUES (?, ?, ?)")
->execute([$id, 'Produto Exemplo', 99.90]);
};
Ao ativar um módulo, apenas os arquivos são sincronizados. Você precisa executar migrations e seeders manualmente via terminal ou interface da IDE.
Injeção de PDO no Repository
O container injeta o PDO automaticamente via constructor injection:
final class ProdutoRepository
{
// PDO é injetado automaticamente pelo container
public function __construct(private readonly PDO $pdo) {}
public function findAll(): array
{
return $this->pdo
->query("SELECT * FROM produtos ORDER BY criado_em DESC")
->fetchAll(PDO::FETCH_ASSOC);
}
public function findById(string $id): ?array
{
// SEMPRE use prepared statements para evitar SQL injection
$stmt = $this->pdo->prepare("SELECT * FROM produtos WHERE id = ?");
$stmt->execute([$id]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ?: null;
}
public function create(array $data): array
{
$id = bin2hex(random_bytes(16));
$stmt = $this->pdo->prepare(
"INSERT INTO produtos (id, nome, preco) VALUES (?, ?, ?)"
);
$stmt->execute([$id, $data['nome'], $data['preco']]);
return $this->findById($id) ?? ['id' => $id];
}
}
NUNCA concatene valores diretamente na query SQL. Use prepare() e execute() com placeholders (?) para evitar SQL injection.
Transações
Use transações para operações que precisam ser atômicas (tudo ou nada):
public function transferir(string $deId, string $paraId, float $valor): void
{
try {
$this->pdo->beginTransaction();
// Debita da conta origem
$stmt = $this->pdo->prepare("UPDATE contas SET saldo = saldo - ? WHERE id = ?");
$stmt->execute([$valor, $deId]);
// Credita na conta destino
$stmt = $this->pdo->prepare("UPDATE contas SET saldo = saldo + ? WHERE id = ?");
$stmt->execute([$valor, $paraId]);
$this->pdo->commit();
} catch (\Throwable $e) {
$this->pdo->rollBack();
throw $e;
}
}
Executando Migrations Manualmente
Após ativar um módulo, você precisa executar as migrations manualmente:
Via Terminal da IDE
# Executar migrations de um módulo específico
php vupi migrate --modules=NomeDoModulo
# Executar migrations de todos os módulos
php vupi migrate --modules
# Executar seeders após migrations
php vupi seed --modules=NomeDoModulo
Via Interface da IDE
Na página do projeto, clique em:
- "Executar Migrations" — Cria as tabelas no banco de dados
- "Executar Seeders" — Insere dados iniciais
Sempre execute migrations antes dos seeders. Migrations criam as tabelas, seeders inserem os dados.
Como Configurar sua Conexão
Existem duas formas de configurar a conexão de banco de dados para seus módulos:
Opção 1: Usar Conexão da Plataforma
Selecione uma conexão pré-configurada pelo administrador e crie um banco de dados default automaticamente.
Vantagens: Configuração rápida, sem precisar informar credenciais manualmente.
Opção 2: Configurar Conexão Própria
Informe manualmente os dados de conexão do seu servidor de banco de dados (local ou em nuvem).
Vantagens: Total controle, use qualquer servidor (Aiven, AWS RDS, local, etc.).
Opção 1: Usando Conexão da Plataforma
Acessar configuração de banco de dados
Na página /dashboard/ide, clique em "Configurar Banco de Dados".
Escolher "Usar conexão da plataforma"
Selecione uma das conexões pré-configuradas disponíveis na lista.
Criar banco de dados default
O sistema criará automaticamente um banco de dados exclusivo para você na conexão selecionada.
Pronto!
Sua conexão está configurada e você já pode criar projetos na IDE.
Esta opção é ideal se você quer começar rapidamente sem se preocupar com configurações de servidor de banco de dados.
Opção 2: Configurando Conexão Própria
Acessar a página de projetos
Na página /dashboard/ide, localize o card "Conexão de Banco de Dados".
Clicar em "Configurar Banco de Dados"
Preencha os campos obrigatórios:
- Nome da conexão: Nome amigável (ex: "Meu PostgreSQL Local")
- Driver: PostgreSQL ou MySQL
- Nome do banco: Nome do database (ex:
meu_banco_dev) - Host: Endereço do servidor (ex:
localhostoupg-xxx.aivencloud.com) - Porta: Porta do banco (ex:
5432para PostgreSQL,3306para MySQL) - Usuário: Nome de usuário do banco
- Senha: Senha do banco de dados
Configurar SSL (opcional)
Para conexões em produção ou com bancos em nuvem:
- Modo SSL: Nenhum, Require, Verify CA ou Verify Full
- Certificado CA: Cole o conteúdo do arquivo
.pem(necessário para Verify CA/Full)
Testar e Conectar
Clique em "Testar Conexão" para validar. Se bem-sucedido, clique em "Conectar" para salvar.
Exemplo: PostgreSQL no Aiven
Nome da conexão: Aiven PostgreSQL
Driver: PostgreSQL
Nome do banco: defaultdb
Host: pg-xxx-yyy.aivencloud.com
Porta: 12345
Usuário: avnadmin
Senha: sua_senha_aiven
Modo SSL: Require
Certificado CA: (cole o conteúdo do ca.pem fornecido pelo Aiven)
Comportamento do sistema
Todos os seus módulos criados na IDE usam automaticamente sua conexão personalizada:
| Tipo de Módulo | Banco Usado |
|---|---|
| Seus módulos (criados na IDE) | ✅ Sua conexão personalizada (obrigatória) |
| Módulos nativos (Auth, Usuario, etc.) | Banco Core (DB_*) — não são afetados |
João configura uma conexão PostgreSQL na IDE. A partir desse momento:
- ✅ João pode criar projetos na IDE
- ✅ Todos os módulos de João usam o PostgreSQL configurado
- ✅ Migrations e seeders executam no PostgreSQL de João
- ✅ Queries dos repositories vão para o PostgreSQL de João
- ❌ Módulos nativos (Auth, Usuario) continuam usando o banco Core
O sistema usa conexões persistentes (PDO::ATTR_PERSISTENT) para melhor performance. Primeira requisição: ~3500ms (estabelece conexão). Requisições subsequentes: ~50-200ms (reutiliza conexão) — 95% mais rápido!
Gerenciamento
No card de banco de dados, você pode:
- Ver/Ocultar dados: Clique no ícone de olho para mostrar/ocultar host, porta e nome do banco
- Ver migrations pendentes: Número de migrations que ainda não foram executadas
- Ver tabelas: Lista de todas as tabelas criadas no banco personalizado
- Editar conexão: Modifique as configurações (senha é mantida se deixar vazio)
- Excluir conexão: Remove a configuração (seus módulos voltam a usar o banco core)
Ao excluir a conexão, seus módulos voltarão a usar o banco de dados padrão da Vupi.us API. As tabelas e dados no banco personalizado não serão afetados.
Segurança
- Criptografia: Senhas são criptografadas com AES-256-CBC antes de serem armazenadas
- SSL/TLS: Suporte completo a conexões seguras com verificação de certificado
- Isolamento: Cada usuário tem sua própria configuração de conexão
Tipos de Dados por Driver
| Tipo | PostgreSQL | MySQL |
|---|---|---|
| ID | UUID | CHAR(36) |
| Texto curto | VARCHAR(255) | VARCHAR(255) |
| Texto longo | TEXT | TEXT |
| Número inteiro | INTEGER | INT |
| Número decimal | DECIMAL(10,2) | DECIMAL(10,2) |
| Booleano | BOOLEAN | TINYINT(1) |
| Data/Hora | TIMESTAMPTZ | DATETIME |
| JSON | JSONB | JSON |
Use $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) nas migrations para criar tabelas compatíveis com PostgreSQL e MySQL.
Validação Prévia de Migrations
Antes de executar migrations, você pode validá-las para detectar problemas sem modificar o banco de dados:
{
"valid": true,
"migrations_found": 3,
"issues": [],
"message": "Todas as migrations são válidas."
}
O que é validado?
- Sintaxe PHP: Verifica se o código é válido
- Métodos obrigatórios: Confirma presença de
up()edown() - Idempotência: Detecta migrations que não verificam se tabelas já existem
- Compatibilidade de driver: Alerta sobre SQL específico de PostgreSQL/MySQL
Sempre valide migrations antes de executá-las, especialmente em produção. Isso evita erros que podem corromper o banco de dados.
Gerenciamento de Tabelas
Deletar Todas as Tabelas (Drop Tables)
Durante o desenvolvimento, você pode precisar resetar completamente o banco de dados. Use esta funcionalidade com extrema cautela:
{
"dropped": ["produtos", "categorias", "pedidos"],
"message": "3 tabelas deletadas com sucesso."
}
Deletar tabelas é permanente. Todos os dados serão perdidos. Use apenas em ambiente de desenvolvimento ou quando tiver certeza absoluta.
Quando usar Drop Tables?
- Resetar desenvolvimento: Começar do zero após mudanças estruturais grandes
- Limpar testes: Remover dados de teste antes de nova bateria de testes
- Corrigir migrations: Quando migrations falharam e deixaram o banco em estado inconsistente
Ativar/Desativar Módulo
Você pode ativar ou desativar seu módulo sem deletá-lo. Módulos desativados não respondem a requisições:
{
"enabled": false
}
{
"message": "Módulo desativado com sucesso.",
"module_name": "MeuModulo",
"enabled": false
}
Casos de Uso
Manutenção
Desative temporariamente o módulo durante manutenção ou atualizações críticas.
Debug
Desative módulos para isolar problemas e identificar conflitos entre módulos.
Testes A/B
Ative/desative funcionalidades para testar diferentes versões do sistema.
Segurança
Desative rapidamente um módulo se detectar comportamento suspeito ou vulnerabilidade.
Desativar: Módulo continua no sistema, mas não responde a requisições. Pode ser reativado a qualquer momento.
Deletar: Remove completamente o módulo, arquivos e opcionalmente as tabelas do banco. Ação irreversível.