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

Sql Parser Laravel Package

phpmyadmin/sql-parser

phpmyadmin/sql-parser is a validating SQL lexer and parser for PHP with a focus on MySQL. It lets you parse, lint, tokenize, format, and analyze SQL queries, and ships with CLI utilities and a Composer-installable library for query discovery and formatting.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require phpmyadmin/sql-parser:^6.0
    

    The package ships its own PSR-4 autoloading (PMA\SQLParser\ → src/), so do not add a manual mapping for vendor/phpmyadmin/sql-parser/src/ in your composer.json — duplicate mappings cause class-resolution confusion after composer dump-autoload.

  2. First Use Case: Parsing a Query

    use PhpMyAdmin\SqlParser\Parser;
    
    $parser = new Parser('SELECT * FROM users WHERE id = 1');
    
    if ($parser->errors) {
        foreach ($parser->errors as $error) {
            // $error->getMessage(), $error->token->position
        }
    }
    
    foreach ($parser->statements as $statement) {
        // $statement is a Statements\Statement subclass (SelectStatement, etc.)
    }
    
  3. Where to Look First

    • Source: src/Parser.php (entry point), src/Statements/ (one class per statement type), src/Components/ (clauses: options, fields, joins, where…).
    • Tests: tests/ — the most reliable documentation of node shapes and formatter output.
    • Formatter: src/Utils/Formatter.php and the Formatter on statements — this, not the AST alone, is what most Laravel use cases actually need.
  4. Version 6.0.1 Notes

    • PHP 8.5 deprecations fixed and PHP 8.6 support added — safe on modern runtimes, no warnings under E_ALL.
    • Test suite now runs on PHPUnit 13; if you vendor this into your own test bootstrap, pin accordingly.

Implementation Patterns

1. Query Validation

Use Case: Reject malformed or unsupported SQL before it hits a raw DB::select().

$parser = new Parser($sql);

if ($parser->errors) {
    abort(400, 'Invalid SQL: ' . $parser->errors[0]->getMessage());
}

6.0.1 fixed a crash (Attempt to read property "keyword" on null, #609) for truncated input like SELECT * FROM — previously that path could throw a PHP error instead of populating $parser->errors, so validation now degrades cleanly.

2. Query Analysis

Use Case: Extract tables/aliases for caching keys, audit logging, or multi-tenant guardrails.

$parser = new Parser($sql);
$statement = $parser->statements[0];

$tables  = $statement->getTables();   // Table components
$aliases = $statement->getAliases();  // alias => name map

6.0.1 (#658) made getAliases() skip null/absent aliases instead of using null as an array offset. If you previously worked around this with array_filter($aliases, fn($k) => $k !== '', ARRAY_FILTER_USE_KEY), you can drop it — but keep the guard if you're on 6.0.0.

3. Query Transformation / Formatting

Use Case: Normalise or pretty-print SQL for logs, admin tools, or generated migrations.

use PhpMyAdmin\SqlParser\Utils\Formatter;

$parser = new Parser($sql);
$output = (new Formatter())->format($sql);

Formatter fixes in 6.0.1 that matter in Laravel logs:

  • JSON path operators (->, ->>) are no longer mangled with stray spaces — important for MySQL JSON queries copied into an admin panel.
  • INSERT building now respects the context's quote style (#631), so identifiers stay backticked or double-quoted consistently instead of silently switching.

4. Index / DDL Validation

Use Case: Validate user-supplied schema changes (e.g. a "create index" admin form).

$parser = new Parser('CREATE INDEX idx ON users (created_at DESC)');
if ($parser->errors) { /* reject */ }

6.0.1 (#636) fixed a hard error when validating indexes with a sort order (ASC/DESC). Before this patch, DESC indexes produced a failure; if you had worked around it by stripping sort orders before parsing, remove that hack.

5. Integration with Laravel

Middleware for raw-SQL endpoints: parse $request->input('sql') and return 422 on $parser->errors. Query logging: in DB::listen(), run the formatter to normalise and mask SQL before writing to your log channel. Eloquent Builder extension: expose ->parseRawSql($sql) on a custom builder that returns $parser->statements — useful for read-only introspection, not for executing.


Gotchas and Tips

Pitfalls

  1. MySQL Dialect Only The parser is MySQL-specific. TOP (SQL Server) or PostgreSQL-only casts/RETURNING will fail. Pre-process or guard by connection driver before parsing.

  2. Errors go to $parser->errors, not exceptions Parsing is non-throwing by default; check the property. Only Builder/Utils code paths throw PhpMyAdmin\SqlParser\Exceptions\*. A try/catch around new Parser() alone will silently let bad SQL through.

  3. AST shape is undocumented Inspect with var_dump($statement) or read tests/ before mutating nodes. Component lists are plain arrays of objects, not a traversable visitor tree — the "rewrite with a callback" style shown in many tutorials does not exist in this package.

  4. Performance on large queries Deeply nested subqueries and huge INSERT ... VALUES batches are slow. Cache parse results by md5($sql) if you parse the same shape repeatedly.

  5. PHP version churn 6.0.1 is clean on 8.5/8.6, but 6.0.0 emits deprecation notices under E_ALL. If your app treats deprecations as failures (Laravel's HandleExceptions + error_reporting(-1)), pin ^6.0.1.

Debugging Tips

  • Dump $parser->errors and $parser->statements — partial parses still populate statements.
  • Run the package's own suite against your edge cases: vendor/bin/phpunit vendor/phpmyadmin/sql-parser/tests (6.0.1 targets PHPUnit 13; you may need a separate PHPUnit install outside your app's constraint).
  • Log the full SQL alongside the error message — component error messages omit the offending token sometimes.

Extension Points

  1. Custom Builder / Component subclasses for reusable fragments (e.g. a pagination component that always emits LIMIT x OFFSET y).
  2. Formatter subclasses to control keyword casing, indentation, and identifier quoting — override before global find/replace hacks.
  3. Context quote style — set the identifier quote character on your Context so INSERT building matches your connection's settings (#631).

Config Quirks

  • No config file, no service provider — this is a standalone library. Nothing to publish; instantiate directly or bind a singleton in your own AppServiceProvider.
  • Default grammar targets MySQL 8.0+; older MySQL/MariaDB syntax may need pre-normalisation.
  • Statement aliasing is case-sensitive in node lookups even though SQL keywords are matched case-insensitively — verify with the actual node class, not the key string.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel