O que é wmn.php?
Biblioteca PHP que expõe o banco Firebird via wmnzeos.dll com FFI. Sem SQL raw nas telas e sem configuração de PDO — você chama métodos e recebe arrays PHP.
Requisitos: PHP 8.0+ | ffi.enable = true no php.ini | wmnzeos.dll acessível | Firebird rodando.
Como incluir
<?php require_once __DIR__ . '/pacote/wmn.php';
Primeiros passos
<?php
require_once __DIR__ . '/pacote/wmn.php';
// Obtém a instância única (singleton)
$db = Wmn::instancia();
// SELECT — retorna array de linhas
$tipos = $db->buscar("SELECT * FROM OS_TIPO ORDER BY DESCRICAO");
// SELECT — só a primeira linha
$tipo = $db->buscarUm("SELECT * FROM OS_TIPO WHERE ID = 1");
// SELECT — valor escalar único
$total = $db->valor("SELECT COUNT(*) AS N FROM OS_TIPO");
// INSERT
$id = $db->proximoId('OS_TIPO');
$db->inserir('OS_TIPO', ['ID' => $id, 'DESCRICAO' => 'Corretiva']);
// UPDATE
$db->atualizar('OS_TIPO', ['DESCRICAO' => 'Preventiva'], 'ID', $id);
// DELETE
$db->deletar('OS_TIPO', $id);Referência rápida
| Método | Retorno | Descrição |
|---|---|---|
Wmn::instancia($dll?) | Wmn | Obtém (ou cria) a instância única |
buscar($sql) | array[] | Executa SELECT → array de linhas |
buscarUm($sql) | array|null | Primeira linha ou null |
valor($sql) | mixed | Primeira coluna da primeira linha |
inserir($tabela, $dados) | array | Insere registro e retorna dados inseridos |
atualizar($tabela, $dados, $campo, $id) | array | Atualiza e retorna registro atualizado |
deletar($tabela, $id) | bool | Exclui pelo ID — lança exceção em falha |
proximoId($tabela, $campo?) | int | MAX(campo)+1 — próximo ID livre |
existe($tabela, $where) | bool | Verifica se existe ao menos um registro |
contar($tabela, $where?) | int | COUNT(*) com WHERE opcional |
definirIni($caminho) | void | Aponta para outro arquivo .ini de conexão |
fechar() | void | Fecha a conexão com o banco |
ultimoErro() | string | Última mensagem de erro da DLL |
Conexão com o banco
Wmn::instancia() — singleton
O padrão singleton garante que toda a requisição PHP use a mesma conexão. O caminho da DLL só é usado na primeira chamada.
// Usa o caminho padrão (C:\wayssoft\wmn\w1\devkit\wmnzeos.dll)
$db = Wmn::instancia();
// Ou aponta para uma DLL em outro local (apenas na primeira chamada)
$db = Wmn::instancia('C:\\meu_projeto\\wmnzeos.dll');
// Chamadas posteriores retornam a mesma instância
$db2 = Wmn::instancia(); // mesma instância que $dbdefinirIni() — trocar a configuração de conexão
Use quando precisar conectar a bancos diferentes em ambientes distintos.
$db = Wmn::instancia();
// Aponta para outro .ini (host, porta, banco, usuário, senha)
$db->definirIni('C:\\configs\\producao.ini');fechar() e ultimoErro()
$db = Wmn::instancia();
// Encerra a conexão (opcional — ocorre ao fim do processo)
$db->fechar();
// Lê a última mensagem de erro registrada pela DLL
$msg = $db->ultimoErro();
if ($msg !== '') {
echo 'Erro DLL: ' . $msg;
}Consultas (SELECT)
buscar() — múltiplas linhas
Cada linha é um array cujas chaves são os nomes das colunas em maiúsculas (ex.: $linha['DESCRICAO']).
$db = Wmn::instancia();
// Todas as linhas
$tipos = $db->buscar("SELECT ID, DESCRICAO FROM OS_TIPO ORDER BY DESCRICAO");
foreach ($tipos as $t) {
echo $t['ID'] . ' — ' . $t['DESCRICAO'] . PHP_EOL;
}
// Com WHERE
$abertos = $db->buscar("SELECT * FROM OS_ORDENS WHERE STATUS = 'A' AND ID_CLIENTE = 10");
// Com FIRST (Firebird — equivale ao LIMIT do MySQL)
$ultimos = $db->buscar("SELECT FIRST 5 * FROM OS_ORDENS ORDER BY DATA_ABERTURA DESC");buscarUm() — primeira linha ou null
Ideal para buscar um registro por ID em páginas de detalhe / edição.
$db = Wmn::instancia();
$os = $db->buscarUm("SELECT * FROM OS_ORDENS WHERE ID = 42");
if ($os === null) {
echo 'Ordem não encontrada.';
} else {
echo 'Cliente: ' . $os['NOME_CLIENTE'];
echo 'Status: ' . $os['STATUS'];
}valor() — valor escalar
Retorna o primeiro campo da primeira linha — perfeito para COUNT, SUM, MAX e subqueries.
$db = Wmn::instancia();
$total = $db->valor("SELECT COUNT(*) AS N FROM CLIENTES");
$faturamento = $db->valor("SELECT SUM(VALOR_TOTAL) FROM PEDIDOS WHERE MES = 6");
$ultimoId = $db->valor("SELECT MAX(ID) FROM OS_ORDENS");
$nome = $db->valor("SELECT NOME FROM CLIENTES WHERE ID = 5");Escrita (INSERT / UPDATE / DELETE)
inserir()
Passe o nome da tabela e um array campo => valor. Use proximoId() para gerar o próximo ID.
$db = Wmn::instancia();
$id = $db->proximoId('OS_TIPO');
$inserido = $db->inserir('OS_TIPO', [
'ID' => $id,
'DESCRICAO' => 'Instalação',
'ATIVO' => 'S',
]);
echo 'Inserido com ID: ' . $inserido['ID'];atualizar()
Informe a tabela, os campos a alterar, o nome da coluna PK e o valor da PK.
$db = Wmn::instancia();
$atualizado = $db->atualizar(
'OS_TIPO', // tabela
['DESCRICAO' => 'Corretiva Urgente', 'ATIVO' => 'S'], // dados
'ID', // campo PK
3 // valor da PK
);
// Caso típico — salvar formulário de edição
$id = (int)$_POST['id'];
$db->atualizar('CLIENTES', [
'NOME' => trim($_POST['nome']),
'EMAIL' => trim($_POST['email']),
'TELEFONE' => trim($_POST['telefone']),
], 'ID', $id);deletar()
Exclui pelo campo ID. Lança WmnException se o banco rejeitar (ex.: FK violada).
$db = Wmn::instancia();
try {
$db->deletar('OS_ORDENS', (int)$_POST['id']);
$mensagem = 'Registro excluído com sucesso.';
} catch (WmnException $e) {
$mensagem = 'Não foi possível excluir: ' . $e->getMessage();
// Pode ser FK — o registro está sendo usado em outra tabela
}Utilitários
proximoId() — MAX(ID) + 1
Calcula o próximo ID livre para uma tabela com PK numérica. Retorna 1 quando a tabela está vazia.
$db = Wmn::instancia();
$id = $db->proximoId('OS_TIPO'); // coluna "ID" por padrão
$id = $db->proximoId('LANCAMENTOS', 'NUM_LANC'); // outra coluna PKexiste() — validação rápida
Útil para evitar duplicatas antes de inserir ou verificar vínculos/permissões.
$db = Wmn::instancia();
// Verificar duplicata antes de inserir
if ($db->existe('FUNCIONARIOS', "LOGIN = '{$login}'")) {
echo 'Este login já está em uso.';
}
// Verificar vínculo antes de excluir
if ($db->existe('OS_ORDENS', "ID_TIPO = {$id}")) {
echo 'Tipo está em uso — não pode ser excluído.';
}contar() — COUNT(*) com WHERE opcional
$db = Wmn::instancia();
$totalClientes = $db->contar('CLIENTES');
$ativos = $db->contar('FUNCIONARIOS', "STATUS = 'A'");
$stats = [
'clientes' => $db->contar('CLIENTES'),
'os_abertas' => $db->contar('OS_ORDENS', "STATUS = 'A'"),
'os_fechadas' => $db->contar('OS_ORDENS', "STATUS = 'F'"),
];Tratamento de erros
WmnException
WmnException estende RuntimeException. Use try/catch para capturar falhas de banco, DLL não encontrada, violação de FK, etc.
try {
$db = Wmn::instancia();
$db->inserir('PRODUTOS', ['ID' => 1, 'NOME' => 'Parafuso']);
} catch (WmnException $e) {
echo 'Erro de banco: ' . $e->getMessage();
} catch (\Throwable $e) {
echo 'Erro inesperado: ' . $e->getMessage();
}Erros comuns e causas
| Mensagem | Causa provável | Solução |
|---|---|---|
| FFI não está habilitada | ffi.enable = false no php.ini | Setar ffi.enable = true e reiniciar o PHP |
| DLL não encontrada | Caminho da DLL errado ou ausente | Verificar o caminho passado em instancia() |
| Falha ao carregar a DLL | DLL incompatível ou dependência ausente | Verificar se wmnzeos.dll e suas deps estão presentes |
| Erro na busca: … | SQL inválido ou tabela inexistente | Revisar o SQL e os nomes das colunas |
| Falha ao inserir: … | Violação de UK/NOT NULL/tipo errado | Verificar restrições da tabela no banco |
| Erro ao deletar: … | FK — registro referenciado em outra tabela | Excluir dependentes primeiro ou usar existe() |
Padrão recomendado para APIs (JSON)
<?php
// api/os_tipo.php
header('Content-Type: application/json; charset=utf-8');
require_once dirname(__DIR__) . '/pacote/wmn.php';
try {
$db = Wmn::instancia();
$action = $_GET['action'] ?? '';
if ($action === 'listar') {
echo json_encode($db->buscar("SELECT * FROM OS_TIPO ORDER BY DESCRICAO"));
} elseif ($action === 'salvar' && $_SERVER['REQUEST_METHOD'] === 'POST') {
$dados = json_decode(file_get_contents('php://input'), true);
$id = (int)($dados['ID'] ?? 0);
$ret = $id === 0
? $db->inserir('OS_TIPO', $dados + ['ID' => $db->proximoId('OS_TIPO')])
: $db->atualizar('OS_TIPO', $dados, 'ID', $id);
echo json_encode(['sucesso' => true, 'dados' => $ret]);
} else {
http_response_code(400);
echo json_encode(['erro' => 'action inválida']);
}
} catch (WmnException $e) {
http_response_code(500);
echo json_encode(['erro' => $e->getMessage()]);
}Exemplos completos
Tela de manutenção (lista + ações)
Padrão típico: lista os registros com buscar() e renderiza a tabela com WmnUI; inserir/editar via modal JS e excluir com confirmação.
<?php
require_once __DIR__ . '/pacote/wmn.php';
require_once __DIR__ . '/pacote/wmnui.php';
$db = Wmn::instancia();
$tipos = $db->buscar("SELECT ID, DESCRICAO, ATIVO FROM OS_TIPO ORDER BY DESCRICAO");
WmnUI::pagina('Tipos de OS', 'Usuário', function() use ($tipos) {
WmnUI::cabecalho('Tipos de OS', 'Manutenção', function() {
WmnUI::botao('+ Novo', '', 'primary', 'onclick="abrirForm(0)"');
});
WmnUI::conteudo(function() use ($tipos) {
WmnUI::tabela(
['ID', 'Descrição', 'Ativo', 'Ações'],
array_map(fn($t) => [
$t['ID'],
$t['DESCRICAO'],
fn() => WmnUI::badge($t['ATIVO'] === 'S' ? 'Sim' : 'Não',
$t['ATIVO'] === 'S' ? 'success' : 'error'),
fn() => WmnUI::grupoBotoes(function() use ($t) {
WmnUI::botao('Editar', '', 'small', 'onclick="abrirForm(' . $t['ID'] . ')"');
WmnUI::botao('Excluir', '', 'small reject', 'onclick="excluir(' . $t['ID'] . ')"');
}),
], $tipos),
'Tipos (' . count($tipos) . ')'
);
});
});JavaScript — consumindo a API
// Carregar lista
async function carregarLista() {
const r = await fetch('api/os_tipo.php?action=listar');
const lista = await r.json();
document.getElementById('tbDados').innerHTML = lista.map(t => `
<tr>
<td>${t.ID}</td>
<td>${t.DESCRICAO}</td>
<td>${t.ATIVO === 'S' ? 'Sim' : 'Não'}</td>
</tr>`).join('');
}
// Salvar (POST com JSON)
async function salvar(dados) {
const r = await fetch('api/os_tipo.php?action=salvar', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(dados),
});
const res = await r.json();
if (res.erro) { alert('Erro: ' + res.erro); return; }
carregarLista();
}
carregarLista();wmn.php (dados) com WmnUI (interface) para construir telas completas do sistema com pouquíssimo código.