Apps (Coming Soon) 32 / 32
Database
A Livewire-powered database browser for Laravel — list your app's tables and search, sort, paginate, and inline-edit records. It ships in the default WASM app at /database so you can inspect a running app's data right in the browser.
devdojo/database is a Livewire-powered database browser. It lists your application's tables and lets you search, sort, paginate, and edit records inline — two Livewire components you drop onto a page, with no external tool or SQL client required. It leans entirely on Laravel's schema introspection (Schema::getTableListing(), Schema::getColumnListing()) and the query builder, so it works against any connection Laravel supports.
In the DevDojo Platform it is a first-class part of the developer experience: the default app template ships a /database page so you can inspect a running app's data right in the browser.
Overview
The package is intentionally minimal — two Livewire components, one support class, and one config file:
devdojo.tables— the left-hand list of tables. It reads the visible table names (minus exclusions, plus pinned ordering) and emits aselectTableevent when one is clicked.devdojo.database— the right-hand records grid for the selected table. It handles search, sort, pagination, and an inline entry editor, and listens forselectTable.TableManager— the schema-introspection helper that both components use to resolve table names and columns.
The two components communicate over Livewire events, so you can lay them out however you like.
Requirements
- PHP 8.3+.
- A Laravel application with Livewire 3 installed — the package ships plain Livewire components and relies on the host app for the framework and Livewire runtime.
- Any database connection Laravel supports; the browser introspects whatever schema your default connection exposes.
Installation
composer require devdojo/database
The service provider is auto-discovered and registers the two Livewire components immediately — no publish step is required to start using it. Optionally publish the config to customize which tables appear:
php artisan vendor:publish --tag=devdojo-database-config
This writes config/devdojo-database.php.
Warning — the browser reads and writes arbitrary tables with no field-level validation, and the package ships no auth gating of its own. Expose it only to trusted users behind auth (as the platform does), or gate the page in your own middleware. It's a development / admin tool, not something to ship to end users.
Usage
Drop the two Livewire components onto any page:
@livewire('devdojo.tables')
@livewire('devdojo.database')
A typical two-pane layout — a table list on the left, the records grid on the right:
<div class="grid grid-cols-1 gap-5 lg:grid-cols-[16rem_minmax(0,1fr)]">
<aside>
@livewire('devdojo.tables')
</aside>
<section>
@livewire('devdojo.database')
</section>
</div>
Both @livewire('devdojo.tables') and <livewire:devdojo.tables /> syntaxes work. The list component dispatches selectTable when a row is clicked, and the database component listens for it via #[On('selectTable')], so wiring is automatic when both are on the page.
Configuration
config/devdojo-database.php controls which tables are shown and how records are searched:
return [
// Tables hidden from the browser.
'table-exclude' => [
'migrations', 'password_reset_tokens', 'sessions',
'cache', 'cache_locks', 'jobs', 'job_batches', 'failed_jobs',
],
// Tables pinned to the top of the list, in order.
'table-order' => ['users'],
// Optional per-table searchable columns. Unlisted tables
// fall back to searching across all of their columns.
'searchable' => [
// 'users' => ['name', 'email'],
],
];
| Key | Default | Purpose |
|---|---|---|
table-exclude |
framework tables (migrations, sessions, cache, jobs, …) |
Table names hidden from the list. |
table-order |
['users'] |
Tables pinned to the front of the list, in the given order; everything else follows. |
searchable |
[] |
Per-table array of searchable columns. Tables not listed fall back to searching every column with LIKE. |
How it's wired
DatabaseServiceProvider does the whole setup in boot():
$this->loadViewsFrom(__DIR__, 'database');
Livewire::component('devdojo.database', Database::class);
Livewire::component('devdojo.tables', Tables::class);
It also merges the package config under the devdojo-database key and, in console, exposes the devdojo-database-config publish tag. That's the entire footprint: no routes, no migrations, no commands.
TableManager
DevDojo\Database\Support\TableManager is the schema layer both components rely on:
| Method | Returns |
|---|---|
tableNames() |
Visible table names — Schema::getTableListing(schemaQualified: false) minus table-exclude, then reordered by table-order. |
tables() |
The same list mapped to ['name' => …, 'rows' => count]. |
columns($table) |
Schema::getColumnListing($table). |
Table names are read unqualified (schemaQualified: false), so the list shows plain table names regardless of the schema/search-path your connection uses.
The Tables component
Tables is thin: on mount() it loads TableManager::tableNames() into $tables and defaults the selection to users. Clicking a table dispatches selectTable to the database component.
The Database component
Database is where the interaction lives. Public state includes $table, $search, $paginate (default 15), $sortColumn / $sortDirection, and the inline-editor fields $primaryKey, $primaryKeyValue, and $entryArray. It uses Livewire's WithPagination.
- Table selection —
#[On('selectTable')]switches$table, clears the inline editor, and resets pagination to page one. - Sorting —
sortBy($column)togglesasc/descon the active column or switches to a new column (ascending). - Search — when
$searchis non-empty,render()builds anorWhere(… LIKE %term%)across the table'ssearchablecolumns (from config) or, if none are configured, across every column. - Pagination — the filtered, sorted query is
select($columns)->paginate($this->paginate). - Inline editing —
#[On('loadEntry')]loads a single record (by primary key) into$entryArray;saveEntry()diffs the edited array against the stored record and issues a targetedDB::table(...)->where(primaryKey, value)->update([...])for each changed column, then dispatcheshide-entry-editorandentry-saved.
Note — the component assumes an id column: $primaryKey and the default $sortColumn are both 'id'. Tables without an id column (composite-key pivots, for example) will list but can't be reliably sorted or inline-edited. Edits are written with the query builder as-is — there is no validation, casting, or transaction around saveEntry().
In the DevDojo Platform
The default DevDojo Platform app template requires devdojo/database and ships a /database page (a Folio page behind auth) that mounts both components inside the app's dashboard layout:
{{-- resources/views/pages/database.blade.php (default WASM app) --}}
<x-layouts.dashboard :title="'Database — '.config('app.name')">
<aside>
@livewire('devdojo.tables')
</aside>
<section>
@livewire('devdojo.database')
</section>
</x-layouts.dashboard>
Because a platform app runs entirely in the browser via php-wasm against a bundled SQLite database, this page lets you browse and edit the live data of the running app without leaving the tab — the queries execute inside the WASM instance, not on a server.
Extension points
- Curate the table list — use
table-excludeandtable-orderinconfig/devdojo-database.phpto hide noise and pin the tables you care about. - Tune search — set per-table
searchablecolumns to narrowLIKEsearches to meaningful fields (and avoid scanning large text columns). - Custom layout — the two components are independent Livewire components; place, style, and wrap them however you like using the components library.
- Guard access — always mount the browser behind auth/authorization middleware, since it can mutate any table with an
idprimary key.