Releases: monicahq/laradb
Release list
1.1.0
1.1.0
Laravel 13 support.
- illuminate/database, http, routing, support and view now accept ^13.0
alongside ^10.0, ^11.0 and ^12.0. - orchestra/testbench widened to ^11.0 for the Laravel 13 leg.
- The package's own PHP floor stays at ^8.1; Composer resolves the pair per
project, so Laravel 13's PHP 8.3 requirement does not reach projects on
older framework versions. - The integration matrix grows from 9 jobs to 11, excluding Laravel 13 on
PHP 8.1 and 8.2.
1.0.1
A security release. If you are on 1.0.0, upgrade.
composer require --dev monicahq/laradb:^1.0.1Both issues were found in an audit of the package rather than reported from the field, and neither is known to have been exploited. Both are cases of a protection that looks present and is not, so neither would have been visible from the page.
An empty middleware config published the viewer unauthenticated
Laravel drops a route group's middleware key when it is not set. A published config with 'middleware' => null — a blank line, a commented-out array, a bad merge — therefore registered both routes with no middleware at all, making every row of every table readable by anyone who found the URL. The ['web', 'auth'] default in the service provider did not catch this, because Config::get() returns null for a key that exists holding null, not the default.
null and [] now fall back to ['web', 'auth']. If you genuinely want the viewer reachable without authentication, say so explicitly with ['web'].
Check your own config: if laradb.middleware is blank, null, or an empty array, your viewer has been unprotected wherever it was enabled. In local that is usually a machine only you can reach — but check anything you enabled with LARADB_ENABLED.
Query failures described the database to the visitor
QueryFailedException embedded the raw PDO message, which quotes the failing statement, the schema it ran against and, on PostgreSQL, the value that broke it. It reached the HTML page and the JSON endpoint alike, and it was reachable from the query string — a foreign key filter with a value of the wrong type is enough to provoke one on PostgreSQL.
The message is generic now. Every exception on its way to a visitor passes through a single method that sends the real cause to the application log, so sanitising is not something a future code path can forget to do.
Also in this release
Documentation only: the readme opens with the problem the package solves, and the foreign-key section was folded into the Routes table.
Verification
Both fixes are covered by tests that fail against 1.0.0's code. The suite — Pint, PHPStan level 8 with strict rules, and 129 tests — passes, and the integration matrix ran green on this commit across PHP 8.1–8.4 × Laravel 10/11/12 against real MySQL and PostgreSQL servers.
Full changelog: 1.0.0...1.0.1
1.0.0
A read-only database browser you drop into a Laravel application. Install it, open /db, and get your tables on the left and their rows on the right.
Works with MySQL / MariaDB, PostgreSQL and SQLite.
composer require --dev monicahq/laradbWhat you get
- Every table in the schema in the sidebar, with row counts — exact on SQLite, engine estimates on MySQL and PostgreSQL so listing a large schema stays cheap.
- The grid, dense and monospace: column types,
PKandFKbadges, absolute row numbers in a gutter that stays put when you scroll sideways, andNULLrendered as something you can tell apart from an empty string. - Follow a foreign key through to the row it points at. The value is a link; clicking it lands you on the target table narrowed to that row, with a chip naming the key you came through.
- The chrome tells you where you are: engine and version, the database being browsed, its size and index count, the settings the engine reports about itself — and, for the page in front of you, the statement that produced it and how long it took.
- No CDN. The page ships its own CSS and JavaScript. No build step, no Tailwind, no Alpine. The only remote request is a webfont, and the layout is intact without it.
- A JSON endpoint on
/db/tables/{table}?format=jsonfor when you want the rows rather than the page.
Read-only by construction
The interesting part of a database browser is what it refuses to do.
- Both routes are
GET; the package issues nothing butSELECT. - Table names are matched against schema introspection before anything is built — a name outside that whitelist is a 404, never a query.
- Identifiers are quoted per engine, inner quotes doubled, so a table named
we"irdcannot break out of one. LIMITandOFFSETare integers from arithmetic, never interpolated strings.- The one value that comes from the URL — the foreign-key filter — is always bound, and its column must be one a foreign key actually targets.
- There is no query box. The package cannot run arbitrary SQL because it has nowhere to accept it.
- Connection errors are sanitised: PDO quotes the DSN and the database user, so the page shows a neutral message and the real error goes to your log.
- SQLite's absolute file path is shortened to the project root, or the bare filename when it lives outside.
Before you install it
It renders the contents of your database in a web page. Install it with composer require --dev, keep it out of production builds, and put an authorisation gate in front of it — the default ['web', 'auth'] middleware only proves the visitor is someone. See Who can reach it.
Requirements
PHP 8.1+ · Laravel 10, 11 or 12 · ext-pdo
Tested on CI against PHP 8.1–8.4 × Laravel 10/11/12, with real MySQL and PostgreSQL servers.