vicgutt/laravel-inspect-db
Inspect your Laravel database from the command line: list tables, columns, indexes, and foreign keys with clear Artisan commands, making schema exploration and debugging quick and easy without leaving your terminal.
This is a small, single-purpose package (~1 star, no dependents, last release March 2023), so the fastest path is to read the source before writing any code. Clone or composer require vicgutt/laravel-inspect-db and treat the src/ directory as the source of truth — the README is thin, but the class surface is small enough to audit in a few minutes.
Minimal setup:
composer require vicgutt/laravel-inspect-db (pin it: "vicgutt/laravel-inspect-db": "^1.0" — there is no active release cadence to rely on).php artisan about or check bootstrap/cache/packages.php. If discovery fails, add VicGUTT\LaravelInspectDb\InspectDbServiceProvider::class to config/app.php.Schema/Connection introspection. Whatever the inspector returns (tables, columns, types, indexes, foreign keys) is the shape you'll be pattern-matching against.Where to look first:
src/ — the inspector class, the facade (if one exists), and any DTOs/value objects returned from introspection.config/ — check whether connections, ignored tables, or cache TTLs are configurable, and publish with php artisan vendor:publish --tag=inspect-db-config if present.tests/ — if present, the fixtures are the best documentation of the returned data shape.First use case — a schema audit command. This is the lowest-risk, highest-value entry point:
// app/Console/Commands/SchemaAudit.php
public function handle(/* injected inspector */): int
{
foreach (config('database.connections') as $name => $cfg) {
if ($cfg['driver'] !== 'mysql') {
continue;
}
// whatever the package exposes: tables(), columns($table), indexes($table), etc.
// Adjust to the exact method names found in src/.
$tables = app(/* Inspector class */)->connection($name)->tables();
$this->table(['Connection', 'Table', 'Columns'], collect($tables)->map(
fn ($t) => [$name, $t, count(/* columns for $t */)]
));
}
return self::SUCCESS;
}
Run this against a scratch database before pointing it at production. You should get a printed list of every table and its attributes — that's the moment you know the package works in your environment and what its return shape actually looks like.
Wrap it, don't sprinkle it. Because this is a low-maintenance dependency, put a thin adapter between your app and the package. That gives you one place to swap, patch, or vendor the code later, and keeps the rest of your app free of a VicGUTT\... import:
// app/Support/SchemaInspector.php
final class SchemaInspector
{
public function __construct(private /* Inspector */ $inspector) {}
public function tables(?string $connection = null): array { /* delegate */ }
public function columns(string $table, ?string $connection = null): array { /* delegate */ }
}
Multi-connection inspection. Most real projects have a reporting DB, a legacy DB, and the primary. If the inspector takes a connection name (either in the constructor or per-call), drive it from config('database.connections') and skip non-relational drivers (sqlite with an empty file, mongodb, etc.). If it only reads the default connection, set config(['database.default' => $name]) around the call — ugly but often the only option with a package this small.
Use it in CI, not just at the CLI. The most valuable day-to-day pattern is a drift check: compare the live schema to what your migrations or SQL dump define. A cheap version:
// tests/Feature/SchemaDriftTest.php
public function test_expected_tables_exist(): void
{
$actual = array_map(fn ($t) => $t->name ?? $t, $this->inspector->tables());
$this->assertEmpty(
array_diff($this->expectedTables(), $actual),
'Schema drift detected: missing tables'
);
}
Pair with RefreshDatabase for a local sanity check, or point it at a staging connection in a nightly job.
Use for codegen. Introspect a connection and generate Eloquent models, FormRequests, or API resources. Since the inspector gives you columns, types, and nullability, a small artisan command can emit skeletons for a legacy database you can't run migrate:fresh against — that's the classic reason someone reaches for a package like this.
Integrate with migrations cautiously. Do not call the inspector from inside a migration that creates the tables it inspects. Only use it in migrations that adapt an existing schema (renames, backfills, conditional column adds):
if (! $inspector->hasTable('legacy_users')) {
return;
}
Cache the results. Introspection is a series of information_schema queries. Wrap it in Cache::remember("schema:{$connection}", now()->addMinutes(30), ...) and bust on deploy. This turns an O(tables) query storm into a single hit.
src/ into app/Support/ and maintain it there. MIT license makes this painless.Schema builder changes or newer PHP 8.3/8.4 deprecations. A quick composer update --dry-run in a scratch project will tell you whether it resolves cleanly.doctrine/dbal, be aware that Laravel also uses DBAL for some schema operations, and version conflicts are a common failure mode. Check composer why doctrine/dbal after install.information_schema permissions. On MySQL/Postgres, introspection needs SELECT on information_schema (usually granted) and sometimes REFERENCES/SHOW VIEW. On a locked-down RDS user it may return partial results silently — cross-check table counts against SHOW TABLES.int vs integer, varchar vs character varying). Never hardcode a comparison against a MySQL type string.// shape: comment or a small PHPStan type stub. This is where most integration bugs will come from.php artisan about) before assuming a driver issue. If it returns empty arrays on a working DB, log the underlying connection name the inspector used — default-connection mismatches are the #1 cause.How can I help you explore Laravel packages today?