Skip to content

Add phpMyAdmin Ask AI plugin#20307

Open
andyg2 wants to merge 2 commits into
phpmyadmin:masterfrom
andyg2:phpMyAdmin-Ask-AI
Open

Add phpMyAdmin Ask AI plugin#20307
andyg2 wants to merge 2 commits into
phpmyadmin:masterfrom
andyg2:phpMyAdmin-Ask-AI

Conversation

@andyg2

@andyg2 andyg2 commented May 18, 2026

Copy link
Copy Markdown

Ref: https://www.reddit.com/r/phpmyadmin/comments/1tgn2aq/comment/omie0gg/

Adds an "Ask AI" button next to "Get auto-saved query" on the SQL tab. Users describe a query in natural language; the configured LLM returnsa SQL (or a clarifying question) that drops into phpMyAdmin's CodeMirror editor for review before the user clicks Go.

No phpMyAdmin core files are modified. The plugin attaches via the existing customFooterFile extension point, with a 3-line stub the user copies to /config.footer.inc.php on install.

Layout:

phpMyAdmin-Ask-AI/
main.php - hidden modal + JS that injects the
button and survives AJAX nav via a
MutationObserver on #page_content
ai_query.php - AJAX endpoint, bootstrapped through
Common::run() so it inherits the
phpMyAdmin session, CSRF token, and
$dbi handle (get_config / save_config
/ generate actions)
install/
config.footer.inc.php - 3-line include stub for the root
.htaccess - denies web access to ai_query.config.json
.gitignore - excludes ai_query.config.json (keys)
README.md
LICENSE (MIT)

Schema-aware prompts: sends INFORMATION_SCHEMA for the active DB plus SHOW CREATE TABLE and 3 sample rows for the focused table, with a hint that the focused table is just where the user happened to be. Falls back gracefully when the logged-in MySQL user lacks privileges.

Multi-provider settings UI (per-provider profile storage) covers Anthropic, OpenAI, OpenRouter, Groq, DeepSeek, Ollama (installed model detection), and a Custom tab for any OpenAI-compatible or Anthropic-shaped endpoint (LM Studio, vLLM, Azure OpenAI, etc)

Security posture:

  • CSRF: endpoint validates phpMyAdmin's session token per request.
  • Auth: anonymous requests rejkected (inherits phpMyAdmin session).
  • Keys: stored in ai_query.config.json, gitignored, .htaccess-denied from the web (Nginx equivalent block documented in README).
  • Execution: plugin never auto-runs SQL, user clicks Go.
  • Disclosure: schema + 3 sample rows go to the configured provider on each Generate (use Ollama for confidential schemas).

The phpMyAdmin-Ask-AI/.htaccess is force-added (-f) because the phpMyAdmin .gitignore excludes all .htaccess files repo-wide and this file is security-critical to the plugin.

Tested on phpMyAdmin 5.2.1 with PHP 7.2.5+ (curl extension required).

Description

Please describe your pull request.

Fixes #

Before submitting pull request, please review the following checklist:

  • Make sure you have read our CONTRIBUTING.md document.
  • Make sure you are making a pull request against the correct branch. For example, for bug fixes in a released version use the corresponding QA branch and for new features use the master branch. If you have a doubt, you can ask as a comment in the bug report or on the mailing list.
  • Every commit has proper Signed-off-by line as described in our DCO. This ensures that the work you're submitting is your own creation.
  • Every commit has a descriptive commit message.
  • Every commit is needed on its own, if you have just minor fixes to previous commits, you can squash them.
  • Any new functionality is covered by tests.

Signed-off-by: Andy Gee andy@dgte.pro

Adds an "Ask AI" button next to "Get auto-saved query" on the SQL tab.
Users describe a query in natural language; the configured LLM returns
SQL (or a clarifying question) that drops into phpMyAdmin's CodeMirror
editor for review before they click Go.

No phpMyAdmin core files are modified. The plugin attaches via the
existing customFooterFile extension point, with a 3-line stub the user
copies to <phpmyadmin>/config.footer.inc.php on install.

Layout:

  phpMyAdmin-Ask-AI/
    main.php                  - hidden modal + JS that injects the
                                button and survives AJAX nav via a
                                MutationObserver on #page_content
    ai_query.php              - AJAX endpoint, bootstrapped through
                                Common::run() so it inherits the
                                phpMyAdmin session, CSRF token, and
                                $dbi handle (get_config / save_config
                                / generate actions)
    install/
      config.footer.inc.php   - 3-line include stub for the root
    .htaccess                 - denies web access to ai_query.config.json
    .gitignore                - excludes ai_query.config.json (keys)
    README.md, LICENSE (MIT)

Schema-aware prompts: sends INFORMATION_SCHEMA for the active DB plus
SHOW CREATE TABLE and 3 sample rows for the focused table, with a hint
that the focused table is just where the user happened to be. Falls
back gracefully when the logged-in MySQL user lacks privileges.

Multi-provider settings UI (per-provider profile storage) covers
Anthropic, OpenAI, OpenRouter, Groq, DeepSeek, Ollama (with installed-
model auto-detection), and a Custom tab for any OpenAI-compatible or
Anthropic-shaped endpoint (LM Studio, vLLM, Azure OpenAI, etc.).

Security posture:
  - CSRF: endpoint validates phpMyAdmin's session token per request.
  - Auth: anonymous requests rejected (inherits phpMyAdmin session).
  - Keys: stored in ai_query.config.json, gitignored, .htaccess-denied
    from the web (Nginx equivalent block documented in README).
  - Execution: plugin never auto-runs SQL; user clicks Go.
  - Disclosure: schema + 3 sample rows go to the configured provider
    on each Generate (use Ollama for confidential schemas).

The phpMyAdmin-Ask-AI/.htaccess is force-added (-f) because the
phpMyAdmin .gitignore excludes all .htaccess files repo-wide and this
file is security-critical to the plugin.

Tested on phpMyAdmin 5.2.1 with PHP 7.2.5+ (curl extension required).

Signed-off-by: andyg2 <rehit.it@gmail.com>
Comment thread phpMyAdmin-Ask-AI/.gitignore Outdated
Comment thread phpMyAdmin-Ask-AI/LICENSE Outdated
Comment thread phpMyAdmin-Ask-AI/ai_query.php Outdated
Comment thread phpMyAdmin-Ask-AI/ai_query.php Outdated
andyg2 added a commit to andyg2/phpmyadmin that referenced this pull request May 19, 2026
Four asks from @williamdes, all applied:

  1. Config file moves from .json to .php. A direct web fetch executes
     the file (returns nothing) instead of serving the array literal as
     text - same trust model phpMyAdmin uses for its own config.inc.php.
       phpMyAdmin-Ask-AI/.gitignore
       phpMyAdmin-Ask-AI/ai_query.php  (load + save + $configPath)

  2. ai_load_config() simplified to `$raw = require $path;`. The legacy
     flat-JSON migration block is dropped (clean break; no installed
     users yet besides the author).

  3. ai_save_config() writes via var_export() wrapped in
     `<?php\n\nreturn ...;\n`, producing a real loadable PHP file.

  4. The plugin's MIT LICENSE is removed. The phpMyAdmin repo's root
     LICENSE (GPL-2.0-or-later) governs everything in the tree. README
     license section updated to note the inheritance.

Follow-up adjustment driven by the .php switch: dropped the plugin's
own .htaccess entirely. With the config now a PHP file, the .htaccess
deny was redundant and inconsistent with how phpMyAdmin protects its
own config.inc.php (no companion .htaccess there either). Also removes
the prior force-add against phpMyAdmin's repo-wide .htaccess gitignore.
Users who want defense-in-depth get Apache + Nginx deny snippets in the
new "Optional web-server hardening" README section.

Signed-off-by: Andy Gee <rehit.it@gmail.com>
Signed-off-by: andyg2 <rehit.it@gmail.com>
Four asks from @williamdes, all applied:

  1. Config file moves from .json to .php. A direct web fetch executes
     the file (returns nothing) instead of serving the array literal as
     text - same trust model phpMyAdmin uses for its own config.inc.php.
       phpMyAdmin-Ask-AI/.gitignore
       phpMyAdmin-Ask-AI/ai_query.php  (load + save + $configPath)

  2. ai_load_config() simplified to `$raw = require $path;`. The legacy
     flat-JSON migration block is dropped (clean break; no installed
     users yet besides the author).

  3. ai_save_config() writes via var_export() wrapped in
     `<?php\n\nreturn ...;\n`, producing a real loadable PHP file.

  4. The plugin's MIT LICENSE is removed. The phpMyAdmin repo's root
     LICENSE (GPL-2.0-or-later) governs everything in the tree. README
     license section updated to note the inheritance.

Follow-up adjustment driven by the .php switch: dropped the plugin's
own .htaccess entirely. With the config now a PHP file, the .htaccess
deny was redundant and inconsistent with how phpMyAdmin protects its
own config.inc.php (no companion .htaccess there either). Also removes
the prior force-add against phpMyAdmin's repo-wide .htaccess gitignore.
Users who want defense-in-depth get Apache + Nginx deny snippets in the
new "Optional web-server hardening" README section.

Signed-off-by: andyg2 <rehit.it@gmail.com>
@andyg2 andyg2 force-pushed the phpMyAdmin-Ask-AI branch from b64cd6b to 4955b7f Compare May 19, 2026 12:56
Comment on lines +550 to +557
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
]);
$resp = curl_exec($ch);
$err = curl_error($ch);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any HTTP call should use the class PhpMyAdmin\Utils\HttpRequest

}

try {
if ($action === 'get_config') {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be better to write a controller, as far as I know you can add routes and the system will auto detect new ones.

}

function ai_http_post_json(string $url, array $headers, string $body, int $timeout = 60): array {
$ch = curl_init($url);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use a clean user agent string, but the libraries/classes/Utils/HttpRequest.php already does it for you

Comment on lines +54 to +61
function ai_json(array $data, int $status = 200): void {
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
header('X-Content-Type-Options: nosniff');
header('Cache-Control: no-store');
echo json_encode($data);
exit;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use PSR responses (same subject as controllers)

@MauricioFauth

Copy link
Copy Markdown
Member

I don't think this plugin makes sense in the phpMyAdmin repository. At least not in the way it was developed.

@williamdes

williamdes commented May 22, 2026

Copy link
Copy Markdown
Member

I don't think this plugin makes sense in the phpMyAdmin repository. At least not in the way it was developed.

I agree but I advised the author to open a PR so we can provide feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants