romanzipp/laravel-console-list-columns
A small Laravel package that lets you list a database table's columns directly from the console, showing names, types, and attributes in a clean table. Handy for quickly inspecting schemas while debugging migrations or models.
Install as a dev-only dependency — this is a schema-introspection convenience, not a runtime feature:
composer require romanzipp/laravel-console-list-columns --dev
The package ships a service provider with a single Artisan command. On Laravel 5.5+ package auto-discovery registers it; older apps need the provider added to config/app.php. After install:
php artisan package:discover
php artisan list | grep -i column # confirm the exact signature
php artisan help <command-name>
composer show romanzipp/laravel-console-list-columns # confirm you got 1.2.2+
Where to look first. Open src/ in vendor/romanzipp/laravel-console-list-columns — the command class is short and readable, and is the fastest way to learn which arguments/options it actually accepts (table name filter, connection selector, etc.). Then check composer.json in the vendor directory: as of 1.2.2 the rendering layer is symfony/console rather than phplucidframe/console-table, so the only third-party surface is now a package Laravel already depends on. Finally look at the service provider to confirm whether anything is configurable or published. Do this before wiring it into scripts; the package is small enough that five minutes of reading beats guessing at flags.
First use case. Answering "what does this table actually look like right now?" without a DB GUI, a DESCRIBE, or opening TablePlus against a remote host. Typical triggers:
php artisan <command-name> users
Post-migration verification loop. The highest-value habit is running it immediately after migrate on the table you touched, so drift between what the migration says and what the database did surfaces while the change is still in your head:
php artisan migrate && php artisan <command-name> orders
This catches the classic errors early: a ->nullable() you forgot, a string() that silently became varchar(191) because of an index, a ->default() that never applied.
Schema spec for handoff. Paste the output into PR descriptions, tickets, or docs/schema.md when you change a table. It's a cheap, human-readable artifact that reviewers can read without checking out the branch and running migrations. Since 1.2.2 the table is rendered by Symfony's Table helper, so it pastes cleanly into GitHub-flavored markdown if you keep the borders — but see the parsing warning below.
Multi-connection projects. If your app has a tenant, reporting, or legacy connection, check whether the command accepts a --connection option (see php artisan help). If it doesn't, the common workaround is DB::setDefaultConnection('tenant') isn't viable in a CLI context — instead run with the env var that drives your default connection, or add the connection option yourself in a local copy of the command.
Composer script alias. Because the command name is awkward to type, alias it:
"scripts": {
"columns": "php artisan <command-name>"
}
Then composer columns users. Teams that use this daily tend to add a shell alias instead, so it works outside the project root.
Comparing against Laravel's own view. The package reports raw database metadata. When you care about how Eloquent sees it, pair the two:
Schema::getColumnListing('users'); // names only, framework-level
If the raw output and getColumnListing() disagree, you're looking at a stale connection, a cached schema, or the wrong database entirely — a useful sanity check.
When you need it programmatically. Don't shell out to the command from application code. Reimplement the two lines you need (Schema::getColumns() on Laravel 11+, or a SHOW FULL COLUMNS query) and keep the command purely interactive. This is doubly true after 1.2.2 — see the Symfony Table note in Gotchas.
1.2.2 changes the renderer, not the data. The release swaps phplucidframe/console-table for symfony/console. Concretely:
phplucidframe/console-table dependency is gone — that's a genuine supply-chain improvement, and it removes a transitive constraint that used to fight with modern PHP versions. Worth the upgrade on that basis alone.Table defaults. If you have screenshots, docs, or golden-file tests captured against 1.2.1 output, re-generate them.symfony/console constraint conflict. Laravel already pins symfony/console to a major-version band. If this package's constraint is written for an older band, composer require --dev will either fail or silently downgrade your framework's Symfony components. Run composer why-not romanzipp/laravel-console-list-columns 1.2.2 if resolution gets weird, and check composer show symfony/console before and after install.Table computes widths with Helper::width(), which needs mbstring; without it, non-ASCII content misaligns the borders. Cosmetic, but confusing if you assume the schema is wrong.Still don't parse the output. This warning survives the release and arguably gets stronger: the format is now owned by Symfony's renderer, whose padding and wrapping rules change between Symfony minor versions independently of this package. Anything that scrapes the output will break on a composer update. If you need machine-readable schema, write a small custom command that emits JSON.
The package is still very lightly maintained. 1.2.2 is a single-line dependency swap on a repo with a handful of stars and no dependents, not a revival. Check composer.json's illuminate/* constraint before installing on a modern app — if it stops below your Laravel version, expect doctrine/dbal 3.x breakage (removed introspection APIs, changed column type handling) and be ready to fork. The usual symptom is a Doctrine\DBAL exception, which is the package, not your schema.
Prefer the framework's built-ins where available. Laravel 10.22+ ships php artisan db:table <table> and db:show, which do most of this natively and are maintained. On Laravel 11, Schema::getColumns() gives you structured, driver-agnostic metadata. This package only wins on older Laravel versions or if you specifically prefer its output format.
Install it in require-dev. There is no production reason to ship a schema-dumping command into a deployed app. It adds surface area on a host where someone might run it against a live database.
Driver differences will confuse you. MySQL enum/set, unsigned integer display widths, PostgreSQL's distinction between character varying and text, and SQLite's dynamic typing all render differently — and the package was almost certainly only exercised against MySQL. If a type looks wrong, verify with SHOW CREATE TABLE (MySQL) or \d+ table (Postgres) before assuming the tool is correct.
Raw metadata ≠ Laravel casts. What you see is the database column. It tells you nothing about $casts, accessors, or the model's $table/$primaryKey overrides. Don't let it substitute for reading the model.
Command not registered? Two usual causes: a stale bootstrap cache (php artisan clear-compiled and php artisan config:clear), or an app old enough that auto-discovery doesn't apply — add the provider manually to config/app.php.
Debugging failures. Re-run with -vvv to get the underlying exception. If the command dies on a table with unusual columns (generated columns, spatial types, JSON), the introspection query is choking on that type; scope the command to a normal table to confirm, then patch the command source locally.
Extension point is the class itself. There's no meaningful config to publish. If you need custom behavior — a --json flag, extra connections, filterable output — copy the command into app/Console/Commands, register it under a different name, and keep the vendor package around as reference. Don't patch vendor/. Conveniently, 1.2.2 makes this easier: since the renderer is now symfony/console, you can reuse Symfony\Component\Console\Helper\Table in your forked command with no extra dependency to add.
How can I help you explore Laravel packages today?