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 Soar Laravel Package

guanguans/laravel-soar

Laravel SOAR brings Xiaomi's SOAR SQL optimizer and rewriter to Laravel, offering SQL health scores, index and performance suggestions, and automatic query rewriting via artisan commands, facades, and query logging, so you can catch slow or risky SQL before it hits production.

View on GitHub
Deep Wiki
Context7

Getting Started

Install as a dev dependency (you rarely want SQL rewriting available in production):

composer require guanguans/laravel-soar --dev
php artisan vendor:publish --tag=soar-config

The package is a thin Laravel wrapper around guanguans/soar-php, which in turn shells out to Xiaomi's SOAR Go binary. So there are two moving parts to set up:

  1. Publish and inspect config/soar.php — this is where the binary path, default SOAR CLI options, and (for explain) database connection details live.
  2. Make the SOAR binary available — typically php artisan soar:install (downloads a release for the current platform), or point SOAR_BIN / soar.bin at a binary you manage yourself.

Verify the wiring before writing any code:

php artisan list soar          # see the commands your version registers
php artisan soar:score --sql="select * from users where email = '[email protected]'"

Or from php artisan tinker:

Soar::score("select * from orders where status = 'paid' order by created_at desc");

First real use case: grab a slow query from storage/logs/laravel.log, the MySQL slow query log, or a Sentry/New Relic trace, and run it through soar:score (for a 0–100 health score plus alerts) and soar:rewrite (for a suggested rewrite). That feedback loop — score → rewrite → re-score — is the core value of the package.

Look first at: config/soar.php, php artisan list soar, and the Guanguans\LaravelSoar\Facades\Soar facade, which mirrors the soar-php API (score, syntacticCheck, rewrite, explain, md2html).

Implementation Patterns

Ad-hoc analysis via the facade. The most common day-to-day pattern is dropping suspicious queries into Tinker or a throwaway command:

Soar::score($sql);                 // markdown report by default
Soar::syntacticCheck($sql);        // just parse/validate
Soar::rewrite($sql);               // candidate rewrite
Soar::explain($sql, 'mysql_read'); // needs a configured connection

Option overrides per call. Rather than editing config for one-off reports, layer options:

Soar::withOptions(['-report-type' => 'json', '-max-index-parts' => 3])->score($sql);

This is useful when a command needs machine-readable output while interactive use still wants markdown.

CI / pre-deploy SQL linting. Keep schema changes or hand-written reports in database/sql/ and run a lint step that fails the build on parse errors or low scores:

php artisan soar:lint database/sql/*.sql
# or a scripted loop that exits non-zero on alerts

This catches SELECT *, missing WHERE clauses, and non-sargable predicates before they ship.

Local query listener. In a local-only service provider, hook DB::listen() and score queries that exceed a duration threshold, logging the report to a dedicated channel. This turns SOAR into a passive reviewer that surfaces problems while you develop rather than only when you remember to run it:

DB::listen(function ($query) {
    if ($query->time > 200 && app()->isLocal()) {
        Log::channel('soar')->info(Soar::score($query->sql));
    }
});

Gate this strictly on isLocal() or a feature flag — it shells out to a subprocess per query.

Test assertions. If you generate SQL dynamically (query builders, filters, reporting modules), assert against SOAR in a test:

$sql = Order::where('status', 'paid')->toSql();
$this->assertStringNotContainsString('ALERT', Soar::score($sql));

Prefer asserting on specific known-bad patterns (missing index hints, SELECT *) over a raw numeric score, which drifts between SOAR versions.

Explain on staging, not production. soar:explain (and Soar::explain) executes against a real MySQL connection. Configure a dedicated, read-only connection in config/soar.php pointing at a staging replica, and treat it as a separate environment-specific config from the scoring functionality, which needs no DB at all.

Rewrite → verify loop. Treat rewrite output as a candidate, never as an automatic patch. The pattern that works: copy the rewrite into your query, run EXPLAIN (or soar:explain) to confirm the plan improved, then run the feature's tests to confirm semantics are unchanged.

Wrap it for team workflows. Because it's just a facade, it's easy to build a small App\Support\SqlReview service that combines syntacticCheck, score, and a few opinionated checks, so engineers run one command instead of remembering five.

Gotchas and Tips

  • MySQL dialect only. SOAR parses MySQL. It will produce noise or fail on Postgres/SQLite syntax. Don't wire it into a multi-driver project without guarding on the connection driver.
  • Rewrites are suggestions, not semantics-preserving transformations. SOAR does not know your data distribution or constraints. Always verify with a real EXPLAIN and tests before applying.
  • Score -1 means parse failure, not "terrible query". Distinguish parse errors from low scores when scripting; otherwise a typo in a SQL file silently looks like a performance problem.
  • The binary is a platform dependency. Linux/macOS Go binaries work well; Windows generally needs WSL, and ARM availability varies by SOAR release. Pin the SOAR version explicitly in config so CI and laptops agree — otherwise score output drifts between environments.
  • CI/Docker needs the binary baked in. soar:install downloads at runtime; in locked-down CI you often need to install it in the image or vendor the binary. Check whether your config caches the resolved path.
  • Config caching bites. SOAR_BIN and other env-driven values are frozen after php artisan config:cache. Run php artisan config:clear when changing the binary path or connection details.
  • Option precedence is layered. CLI options passed via withOptions() override the SOAR config file, which overrides SOAR defaults. The Laravel config/soar.php only forwards a subset — if an option seems ignored, check whether it's being passed through to the underlying soar-php call at all.
  • explain requires credentials and permissions. It opens a real connection. Point it at a read replica, scope the user to read-only, and never expose it behind a public endpoint — it leaks schema information and can be used to run expensive queries.
  • Report format matters for scripting. Default output is human-oriented (markdown/HTML, sometimes with ANSI styling). Use -report-type=json (or the equivalent so-php option) when parsing programmatically, and don't scrape the pretty output.
  • Large or multi-statement SQL files. Split statements before analysis; very long IN (...) lists and generated SQL can exceed SOAR's parser limits or produce unhelpful rewrites.
  • Shelling out per query is slow. Each call spawns the SOAR process. For bulk analysis, batch in a queued job or cache results keyed by a hash of the normalized SQL — repeat analyses of the same query are common in test suites.
  • Debugging failures: the underlying soar-php surfaces stderr from the binary, but it's easy to miss. When a command returns nothing useful, run the SOAR binary directly with -v against the same SQL to see whether the problem is the wrapper, the options, or the parser.
  • Extension points are limited but sufficient. Bind your own instance in the container, register macros, or wrap the facade in a domain service. There's no deep Laravel integration (no Blade components, no debugbar panel in most versions) — expect a CLI/facade tool, not a UI.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console