huangdijia/laravel-web-soar
Laravel integration for Web Soar, the PHP extension that profiles slow requests and runtime performance. Provides config publishing, middleware and service wiring, and slow-request reporting so you can trace bottlenecks in Laravel apps without touching raw extension setup.
laravel-web-soar is a thin web UI on top of Xiaomi's SOAR SQL optimizer/rewriter, wired through huangdijia/laravel-soar. You get a browser page that scores a SQL statement, suggests rewrites, and (with a DSN) gives index advice — without SSH-ing to run soar by hand.
Prerequisites
soar binary installed on the host that runs PHP (not just your laptop).huangdijia/laravel-soar available — it's the process wrapper this package renders.path.to.soar config value pointing at the binary.Minimal install
composer require huangdijia/laravel-web-soar
php artisan vendor:publish --provider="Huangdijia\WebSoar\WebSoarServiceProvider"
The service provider is auto-discovered. After publishing you'll have a config/web-soar.php (route prefix, middleware, enabled flag, view/layout options) and the package's Blade views.
Where to look first
config/web-soar.php — route path, middleware stack, enable/disable switch. This is the file you will actually edit.vendor/huangdijia/laravel-web-soar/src/routes/ — the route definitions the package registers, so you know the exact URI and controller.config/soar.php (from laravel-soar) — binary path, DSN/connection, blacklist, and test-DSN used for EXPLAIN.First use case
Boot the app, hit the configured route (typically /web-soar), paste a slow query copied from storage/logs/laravel.log or Telescope, and read back the score, the "heuristic rules" hits, and the rewritten SQL. That loop — copy query, score, rewrite, verify with EXPLAIN — is 90% of day-to-day use.
Lock it behind a gate and middleware. The default route is a diagnostic tool that can leak schema and run EXPLAIN against your DB. Wire it to your existing admin auth:
// config/web-soar.php
'middleware' => ['web', 'auth', 'can:viewWebSoar'],
// AuthServiceProvider
Gate::define('viewWebSoar', fn ($user) => $user->isAdmin());
Register conditionally per environment. Don't rely on the enabled flag alone; guard registration in AppServiceProvider:
if ($this->app->environment(['local', 'staging'])) {
$this->app->register(\Huangdijia\WebSoar\WebSoarServiceProvider::class);
}
Combined with APP_ENV this keeps the route absent in production even if config is mis-set.
Reuse the same engine in Artisan commands and tests. Because the web layer is just a controller over laravel-soar, you can call the facade directly for a CI guardrail:
$result = \Huangdijia\Soar\Facades\Soar::score($sql); // returns score + advice
if ($result['score'] < 80) {
$this->error("SQL scores {$result['score']}: {$sql}");
return 1;
}
Point that at your database/migrations or a queries.sql fixture to catch SELECT *, missing WHERE, and leading-wildcard LIKE before review.
Give SOAR a DSN for index advice. The score/rewrite features work offline, but index suggestions need a connection to inspect information_schema. Configure the test DSN in config/soar.php (SOAR_TEST_DSN style env) against a read replica or a schema-only copy, never the primary. Then the web UI's "index" tab is actually useful.
Publish views when you need to fit it into your admin panel. Publish the views and swap the layout to your own Blade shell (Tailwind/Filament/Nova), or wrap the route in your admin middleware group so the page inherits your chrome. Re-publish only when you intentionally upgrade, otherwise you'll silently miss view fixes.
Workflow pairing. Keep the page open alongside Telescope or Debugbar: copy a slow query out of the queries panel, paste into web-soar, apply the rewrite, then compare EXPLAIN output in your SQL client before committing.
which soar in your terminal proves nothing. Test with sudo -u www-data which soar (or your pool user). A common failure is a silent "command not found" surfacing as a blank result page.proc_open/exec may be disabled. Shared hosts and hardened images routinely block these. Check disable_functions in php.ini; SOAR can't run without them.php artisan route:list | grep -i soar and a logged-out request.web-soar.php or soar.php, run php artisan config:clear. This trips people up constantly in Docker setups where config is cached at build time.soar binary and laravel-soar parser. SOAR's JSON keys have shifted across releases; a mismatched binary yields empty scores or PHP notices about undefined array keys. Pin both huangdijia/laravel-soar and the binary version in your Dockerfile.EXPLAIN runs against real data. Some suggestions require executing the query. Point the DSN at a replica with a statement timeout, or disable the connection-dependent features in staging.EXPLAIN plans can exceed PHP's max_execution_time. Raise it for the route or accept that giant generated queries will fail — that's usually a signal in itself..exe path and escape backslashes in config; the process wrapper shells out and unquoted spaces in C:\Program Files\... break it.composer.json, and if you need behaviour changes, fork or vendor the small controller/view set rather than waiting on upstream. The underlying laravel-soar is the part worth tracking closely; this package is mostly glue.How can I help you explore Laravel packages today?