nilportugues/sql-query-formatter
Lightweight PHP SQL formatter that turns messy, computer-generated queries into clean, human-readable plain text. Preserves data-binding placeholders like :variable and ? while reformatting, making SQL easier to read and debug without adding colors or markup.
## Getting Started
### Minimal Steps
1. **Installation**
Add the package via Composer:
```bash
composer require nilportugues/sql-query-formatter:^1.2.2
Note: This version supports PHP 5.5 (temporarily) but downgrades PHPUnit to v4.x. Ensure your project's composer.json allows this version range:
"require": {
"php": ">=5.5.0",
"phpunit/phpunit": "^4.0"
}
No additional configuration is required—autoload the NilPortugues\SqlFormatter\SqlFormatter class.
First Use Case Format a raw SQL query string for debugging or logging:
use NilPortugues\SqlFormatter\SqlFormatter;
$sql = "SELECT * FROM users WHERE id=1 AND status='active' ORDER BY created_at DESC";
$formatter = new SqlFormatter();
$formatted = $formatter->format($sql);
// Outputs:
// SELECT
// *
// FROM
// users
// WHERE
// id = 1
// AND status = 'active'
// ORDER BY
// created_at DESC
Where to Look First
SqlFormatter class for available methods (e.g., format(), setLineLength()).Debugging Queries
Log formatted queries in Laravel’s app/Exceptions/Handler.php:
public function report(Throwable $exception)
{
if ($exception instanceof QueryException) {
$formatted = (new SqlFormatter())->format($exception->getQuery());
Log::error("Failed Query: " . $formatted);
}
}
Middleware for API Responses
Format SQL in API error responses (e.g., app/Http/Middleware/LogFailedQueries.php):
public function handle($request, Closure $next)
{
try {
return $next($request);
} catch (\Exception $e) {
if (app()->bound('db')) {
$lastQuery = app('db')->getQueryLog()[0] ?? null;
if ($lastQuery) {
$e->getMessage() .= "\nFormatted SQL:\n" . (new SqlFormatter())->format($lastQuery['query']);
}
}
throw $e;
}
}
Service Layer Logging Wrap Eloquent queries in a service class:
class UserService {
public function findActiveUsers()
{
$query = User::where('status', 'active')->toSql();
$formatted = (new SqlFormatter())->format($query);
Log::debug("Executing query:\n" . $formatted);
return User::where('status', 'active')->get();
}
}
Dynamic Formatting
Use the setLineLength() method to control output width (default: 80 chars):
$formatter = new SqlFormatter();
$formatter->setLineLength(120); // Wider lines for logs
$formatted = $formatter->format($sql);
Batch Processing Format multiple queries in a loop (e.g., for migration files or seeders):
$queries = [
"SELECT * FROM posts WHERE user_id = 1",
"UPDATE users SET votes = votes + 1 WHERE id = ?"
];
foreach ($queries as $query) {
echo (new SqlFormatter())->format($query) . "\n\n";
}
Integration with Laravel Debugbar
Extend LaravelDebugbar to show formatted SQL:
// In a Debugbar extension
$data['sql'] = (new SqlFormatter())->format($query);
DB::enableQueryLog() for real-time formatting.// app/Console/Commands/FormatSql.php
public function handle()
{
$sql = file_get_contents($this->argument('file'));
$this->info((new SqlFormatter())->format($sql));
}
Register it in app/Console/Kernel.php:
protected $commands = [
\App\Console\Commands\FormatSql::class,
];
Usage:
php artisan format-sql:format path/to/query.sql
Note: Ensure your composer.json allows PHPUnit v4.x if running tests for this command.PHP Version Limitations
^1.2.2 in composer.json to avoid automatic upgrades that might drop 5.5 support.No SQL Validation
Doctrine\DBAL\Connection).Line Wrapping Quirks
setLineLength() to adjust.Parameter Placeholders
?, :id) are not parsed—only literal values are formatted.WHERE id = ? remains unchanged (no type inference for ?).Case Sensitivity
SELECT, FROM) are lowercase in output, regardless of input case.PHPUnit Version Conflict
phpunit/phpunit version in composer.json or isolate tests for this package.Edge Cases
--, /* */) are stripped. Add them back manually if needed.-- Get active users
SELECT * FROM users WHERE status = 'active'
Output will omit the comment.Logging Formatted Queries
tap() to inspect formatted SQL:
DB::table('users')->where('active', 1)->toSql()
->tap(fn($sql) => Log::debug((new SqlFormatter())->format($sql)));
Custom Formatting
class CustomFormatter extends SqlFormatter {
protected function preProcess($sql) {
// Add logic to handle comments or other edge cases
return parent::preProcess($sql);
}
}
setLineLength()).wordwrap() for line breaks. Override if needed:
$formatter->setLineLength(100);
$formatter->setLineBreak("\n"); // Customize line endings
Pre/Post Processing
Override preProcess() or postProcess() to modify input/output:
class ExtendedFormatter extends SqlFormatter {
protected function postProcess($sql) {
return str_replace('WHERE', '/* FILTER */ WHERE', $sql);
}
}
Syntax Highlighting
Combine with a lexer (e.g., Spatie\SqlFormatter) for colored output in CLI tools.
Database-Specific Dialects
LIMIT vs. FETCH FIRST).How can I help you explore Laravel packages today?