A Monica v3 chega antes do fim de 2026. Reconstruída do zero. Continua de código aberto. Veja o que vem por aí
Monica
Todos os artigos
8 min de leitura

Building Monica: construímos o navegador de base de dados que queríamos para Laravel

Enquanto reconstruíamos o Monica, criámos um pequeno navegador de base de dados só de leitura para Laravel e decidimos publicá-lo como um pacote independente.

Regis Freyd Fundador

Este é mais um artigo da série Building Monica, onde escrevo sobre o processo de reconstruir o Monica de raiz. A maioria dos artigos desta série será provavelmente sobre o produto em si: as relações, os lembretes, a personalização, as atividades, a privacidade e todas as questões que surgem ao tentar representar a vida das pessoas em software. Mas reconstruir uma aplicação grande também produz coisas mais pequenas pelo caminho. O LaraDB é uma delas.

Enquanto trabalhava no Monica v3, dei por mim a passar muito tempo a olhar diretamente para a base de dados. Isto não é particularmente invulgar quando se constrói uma aplicação Laravel. Cria-se um contacto e verifica-se o que foi escrito. Cria-se uma relação e inspecionam-se as linhas relacionadas. Altera-se um lembrete e confirmam-se as datas. Executa-se uma ação, atualizam-se os dados, segue-se uma chave estrangeira, e repete-se o processo muitas vezes ao longo do dia.

Já existem muitas boas formas de fazer isto. O Tinker é útil, mas não é simples nem rápido de usar. Aplicações como o TablePlus, o DBeaver, o phpMyAdmin ou o Adminer podem ser muito úteis, mas não para uma consulta rápida. Uso o TablePlus com regularidade, sobretudo quando preciso de escrever consultas, editar dados ou inspecionar o esquema em detalhe. Mas na maior parte do tempo, enquanto desenvolvia o Monica, não precisava de uma ferramenta de gestão de bases de dados. Só queria uma forma rápida de ver o que estava na base de dados sem sair da aplicação em que já estava a trabalhar.

Foi essa a ideia inicial por trás do LaraDB. Instalar uma dependência de desenvolvimento, ir a /db e ver a base de dados.

composer require --dev monicahq/laradb

O que se obtém é muito simples. As tabelas aparecem à esquerda, as linhas à direita, e a página corre dentro da própria aplicação Laravel. O LaraDB suporta SQLite, MySQL e MariaDB, e PostgreSQL.

O LaraDb a mostrar a tabela value_list_items: a lista das 41 tabelas à esquerda, as respetivas linhas à direita, e as colunas de chaves estrangeiras apresentadas como ligações que se podem seguir.

Um navegador em vez de um gestor de bases de dados

A decisão mais importante que tomámos foi manter o LaraDB só de leitura. Não tem botão de edição, botão de eliminação, formulário de inserção nem consola SQL. As duas rotas expostas pelo pacote são rotas GET, e o pacote apenas emite instruções SELECT.

Em parte é uma decisão de segurança, mas é sobretudo uma questão de âmbito. Já existem ferramentas maduras para gerir bases de dados, e reproduzir um subconjunto das suas funcionalidades dentro do Laravel não tornaria o LaraDB mais útil para o problema que estávamos a tentar resolver.

O pacote evita também aceitar identificadores ou consultas arbitrárias vindas do browser. Uma tabela pedida tem primeiro de existir no esquema descoberto pelo driver. Os identificadores são escapados de acordo com o motor de base de dados. Os valores usados ao seguir chaves estrangeiras são passados como parâmetros ligados. Não há interface para submeter SQL arbitrário porque SQL arbitrário não faz parte do propósito do pacote.

Uma ferramenta pequena pode continuar compreensível se tiver uma tarefa muito precisa. O LaraDB destina-se a responder o que está neste momento na base de dados e como essas linhas se relacionam entre si. Não se destina a tornar-se um substituto de um cliente de base de dados a sério.

Aquilo de que acabámos por precisar

A interface reflete esse âmbito estreito. O LaraDB lista as tabelas do esquema atual e mostra as suas linhas numa tabela densa. Os tipos das colunas são apresentados, as chaves primárias e estrangeiras são identificadas, os valores NULL distinguem-se visualmente das cadeias vazias, e os valores longos são truncados para que colunas grandes de texto ou de JSON não tornem a página inutilizável.

As chaves estrangeiras revelaram-se uma das funcionalidades mais úteis para o Monica. Se uma coluna referencia outra tabela, o seu valor pode ser seguido diretamente. Clicar nele abre a tabela referenciada, filtrada pela linha correspondente. Isto é especialmente útil no Monica v3, porque um número crescente de domínios é representado através de relações explícitas entre várias tabelas em vez de registos grandes e autocontidos.

A página expõe também algum contexto sobre a base de dados e a consulta atuais. Consoante o que o motor de base de dados disponibiliza, o LaraDB pode mostrar o motor e a versão, o nome da base de dados, o tamanho, o número de índices e outros metadados específicos do motor. Para a página atual, mostra ainda a instrução SQL que produziu o resultado e quanto tempo a consulta demorou.

Existe também uma representação em JSON de uma tabela. Foi barata de acrescentar depois de a camada de base de dados estar separada da renderização do HTML, e tem sido útil para inspecionar dados fora da própria página.

O frontend é deliberadamente autónomo. O pacote traz o seu próprio CSS e o seu próprio JavaScript e não depende da cadeia de assets da aplicação anfitriã. Instalar o LaraDB não deveria obrigar a acrescentar uma configuração de Tailwind, uma dependência do Alpine ou mais um passo de compilação a um projeto existente.

A abstração da base de dados tornou-se o verdadeiro trabalho

Mostrar linhas num browser é simples. Suportar SQLite, MySQL e PostgreSQL de forma coerente foi onde acabou por estar a maior parte do trabalho interessante.

Os motores diferem bastante na forma como expõem o esquema e os metadados da base de dados. Listar tabelas, descrever colunas, encontrar chaves primárias, resolver chaves estrangeiras, contar linhas e obter informação ao nível da base de dados exigem consultas diferentes consoante o motor. Até pormenores como o escape de identificadores têm de ser tratados corretamente, em vez de como uma operação SQL genérica.

O LaraDB esconde essas diferenças atrás de uma pequena interface de driver. A camada Laravel pede tabelas, colunas, linhas e metadados sem precisar de saber se a ligação subjacente é SQLite, MySQL ou PostgreSQL.

Uma parte simplificada do contrato tem este aspeto:

public function listTables(): array;

public function getColumns(string $table): array;

public function getRowCount(
    string $table,
    ?RowFilter $filter = null,
): int;

public function getRows(
    string $table,
    int $page,
    int $perPage,
    ?RowFilter $filter = null,
): TablePage;

public function getForeignKeys(string $table): array;

Cada driver de base de dados implementa essas operações de forma diferente, enquanto o resto do LaraDB trabalha com os objetos de resultado comuns devolvidos pela interface.

Uma consequência interessante deste desenho é que o núcleo do código que lê a base de dados não depende de todo do Laravel. Funciona diretamente com PDO. O Laravel trata da descoberta do pacote, da configuração, do routing e da renderização, mas a inspeção da base de dados pode ser usada em separado.

use LaraDb\DriverFactory;

$pdo = new PDO('sqlite:database.sqlite');
$driver = DriverFactory::fromPdo($pdo);

foreach ($driver->listTables() as $table) {
    echo $table->name;
}

Só de leitura não é o mesmo que inofensivo

O facto de o pacote ser só de leitura impede-o de corromper a base de dados, mas não torna inofensivo expor essa base de dados. Um navegador de base de dados pode revelar todas as linhas de todas as tabelas a quem quer que consiga chegar até ele, o que é obviamente uma preocupação séria para uma aplicação como o Monica.

Por essa razão, o LaraDB foi pensado para ser instalado como dependência de desenvolvimento.

composer require --dev monicahq/laradb

Um deploy normal de produção com composer install --no-dev não conterá o pacote. O LaraDB está também desativado por omissão fora do ambiente local, e as suas rotas usam por omissão os middleware web e auth quando estão ativas.

Coisas pequenas que saem de uma reconstrução grande

Quando comecei a série Building Monica, esperava que a maior parte do que escrevesse se centrasse nas grandes decisões de arquitetura e de produto por trás do Monica v3. Isso continuará a ser assim. Mas quero também documentar algumas das ferramentas e ideias mais pequenas que saem da reconstrução, porque também fazem parte do trabalho.

O LaraDB não é uma parte importante do Monica v3, e não está a tentar tornar-se um grande produto por si só. É apenas uma pequena ferramenta de desenvolvimento que eliminou um incómodo recorrente para nós. O pacote é útil precisamente porque o seu âmbito é limitado, e gostava que continuasse assim.

Se trabalha em aplicações Laravel e abre muitas vezes um cliente de base de dados só para inspecionar o que o seu código acabou de escrever, o LaraDB pode ser-lhe útil também.

composer require --dev monicahq/laradb

Depois vá a /db.

O código-fonte está disponível em github.com/monicahq/laradb.

Continuar lendo

2026-08-30 Estamos reconstruindo o Monica

Estamos reconstruindo o Monica a partir do zero, e esta nova série vai documentar como.