Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Ask Database Laravel Package

beyondcode/laravel-ask-database

Ask your database questions in plain English. BeyondCode's package uses AI to translate natural language into SQL queries and returns the results, making data exploration easier without writing SQL yourself.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish (expect friction first).

composer require beyondcode/laravel-ask-database --with-all-dependencies
php artisan vendor:publish --provider="BeyondCode\AskDatabase\AskDatabaseServiceProvider"

The package was last released in February 2023, so the very first thing you do on a modern Laravel app is lose a fight with Composer over the openai-php/laravel / openai-php/client constraint and the php/laravel/framework pins. Budget an hour, not five minutes. If --with-all-dependencies can't resolve against your framework version, stop and fork: composer require beyondcode/laravel-ask-database --no-update then vendor it, or clone into packages/ with a path repository. Do not spend a day forcing a resolution on an archived package.

Configure a disposable target.

Set OPENAI_API_KEY in .env, and immediately point the package at a read-only connection — not your default one. Add a dedicated connection in config/database.php (a replica, a local docker DB, or a staging snapshot) backed by a MySQL/Postgres user with SELECT only. Then set that connection in config/ask-database.php. This is the first thing you do, not a hardening follow-up; the package executes model-authored SQL directly.

First query.

php artisan ask-database "How many users signed up last month?"

Where to look first. Read the source in this order: the service provider, the config file, the console command, and whatever class builds the schema summary and prompt. The whole loop — introspect → prompt → completion → DB::select() → output — is small enough to read end to end in ten minutes, and you need to know exactly what leaves your machine (table names, column names, possibly sample values, plus your question) and what comes back (raw SQL that gets executed).

First real use case. Point it at a non-production schema your team already understands and use it as a schema navigation aid: "which tables reference orders?", "what's the shape of the subscriptions table?". That establishes a baseline for accuracy before anyone trusts it with a business question.

Implementation Patterns

Treat the command as a reference, not an API. The package ships one Artisan command and no first-class service facade you should depend on. The durable pattern is to keep the command for ad-hoc exploration and wrap the prompt→SQL→execute loop in your own service class if you need it programmatically — it's maybe 60 lines, and owning it means you control the allowlist, the row cap, and the logging.

final class NlQuery
{
    public function ask(string $question): array
    {
        $sql = $this->toSql($question);              // your prompt builder + client
        Log::info('nlq', ['q' => $question, 'sql' => $sql, 'user' => auth()->id()]);
        $this->assertAllowed($sql);                  // SELECT-only, allowlisted tables
        return DB::connection('askdb')
            ->select($this->withLimit($sql, 500));
    }
}

Scope the schema you expose. Don't hand the model your whole database. Two effective levers:

  • Curated views. Create a reporting schema of views with readable column names and comments, and point the connection at it. The model gets a smaller, better-named surface, your token bill drops, and accuracy goes up.
  • Table allowlist in config, filtered before the prompt is built. Exclude users, sessions, jobs, failed_jobs, personal_access_tokens, anything with PII.

Establish a "show me the SQL" norm. Make the generated statement visible before it runs — add a --dry-run flag to the command (or a dd($sql) in your fork) and default to using it when someone asks a question they actually care about. The dominant failure mode here is a plausible-but-wrong JOIN or GROUP BY, not an exception; the only cheap defense is reading the SQL.

Chain it into existing tooling. Realistic day-to-day integrations:

  • A Slack slash command or internal endpoint that shells out to Artisan::call('ask-database', [...]) and posts the table back, so support doesn't file a ticket for one number.
  • A Nova/Telescope-adjacent admin panel card, limited to admins, rendering query history from your log table.
  • A pre-deploy smoke check: a fixed list of ten known-answer questions run in CI against a seeded DB, asserting the generated rows match. This is how you detect quality regressions when the underlying model changes under you.

Log everything, in a table. Prompt, generated SQL, row count, latency, token usage, user. It's the only way to answer "who asked what, and was it right?" during a pilot, and it's the artifact you show during a security review.

Cache the schema summary, invalidate on deploy. Re-introspecting on every call is wasteful when the schema changes weekly. Key a cached schema blob on the connection name and flush it in your deploy/migrate hook.

Gotchas and Tips

  • Archived means frozen. No patches, no model updates, no dialect fixes. Fork or vendor it and assign an owner; a composer update three months from now will otherwise silently break you when the pinned OpenAI SDK or model name is retired.
  • The model name is likely hardcoded or defaults to something deprecated. Check the config and the prompt builder. An old text-davinci-003-era default will 404 from OpenAI. Overriding the model should be a config value; if it isn't, that's your first patch.
  • No read-only enforcement, no statement allowlist, no LIMIT, no timeout. All of it is yours. Do all four:
    • connection-level SELECT-only DB user,
    • regex/AST check rejecting INSERT|UPDATE|DELETE|DROP|ALTER|TRUNCATE|GRANT|;,
    • wrap results with an injected LIMIT,
    • SET SESSION max_execution_time / statement_timeout.
  • Silent incorrectness is the real risk. Aggregate and join questions come back confidently wrong. Build a small "golden questions" fixture set with known answers and run it after any prompt/model/config change. Don't let anyone make a business decision off a single unreviewed answer.
  • Token cost scales with schema width and conversation context. Wide schemas are both expensive and less accurate — the model loses the needle. Narrow the surface via views and allowlists before you blame the model.
  • Prompt injection is live. User questions, table/column comments, and any sample data in the prompt can steer the generated SQL. Never feed raw user-supplied strings into the schema summary, and never expose this to untrusted users.
  • Error text can leak. If the package feeds DB exceptions back into a retry loop, connection strings, table names, or column values may land in the provider payload. Inspect the error path; strip it in your fork.
  • API failures have no graceful fallback. Rate limits and outages kill the command outright. Provide a documented "write the SQL yourself" path and a runbook entry — users will hit this in week one.
  • Don't put the key anywhere shared. OPENAI_API_KEY in .env only; never in the published config committed to the repo, and never in a multi-tenant config cache.
  • Dialect reality check. Expect MySQL/Postgres basics. Before trusting it on SQLite or SQL Server, run the golden-question set against a disposable instance of each driver you care about.
  • Debugging tips. Run with -v for full output, tail storage/logs/laravel.log, and temporarily dump the exact prompt string — 90% of "it gave a dumb answer" cases are a truncated, noisy, or stale schema summary.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo