# sql-formatter picks its own highlighter when you pass no argument, which surprises CLI users

> Doctrine's sql-formatter is a small PHP class that indents SQL and optionally highlights it, forked from jdorn's original after an attempt to extract phpMyAdmin's formatter proved impractical. The three methods, format, highlight and compress, cover most of what a debug view needs and nothing beyond it.

**doctrine/sql-formatter** — A lightweight php class for formatting sql statements. Handles automatic indentation and syntax highlighting.

- Repository: https://github.com/doctrine/sql-formatter
- Stars: 1,862 · Forks: 29
- Language: HTML
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/doctrine-sql-formatter

## One class, one format method, no configuration

The API is deliberately small. The `SqlFormatter` class has a `format` method that takes an SQL string and returns a formatted block. The README's usage example loads the Composer autoloader and does exactly that:

```php
<?php
require_once 'vendor/autoload.php';

use Doctrine\SqlFormatter\SqlFormatter;

$query = "SELECT count(*),`Column1`,`Testing`, `Testing Three` FROM `Table1`
    WHERE Column1 = 'testing' AND ( (`Column2` = `Column3` OR Column4 >= NOW()) )
    GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10";

echo (new SqlFormatter())->format($query);
```

The namespace is `Doctrine\SqlFormatter` even though the repository lives under the `doctrine` organisation as `sql-formatter`.

There is no config file, no plugin chain and no schema. The whole package is a class with methods, and the trade-off is that it does one job.

The fork's history is explained in the README, and it is a good indicator of the design constraints. The original author wrote that he kept having to debug auto-generated SQL and wanted formatted HTML output without including a huge library or pasting into an online formatter, and that he had originally planned to extract the formatting code from phpMyAdmin before finding it was 10,000+ lines using global variables. So the constraint that shaped this code is size, and it is still visible in how little the API offers.

## NullHighlighter is how you get plain text

Syntax highlighting is not a separate step you configure. It is a `Highlighter` implementation passed into the constructor, and the default is chosen for you.

If you only want indentation and line breaks, you pass a `NullHighlighter`:

```php
<?php

use Doctrine\SqlFormatter\NullHighlighter;
use Doctrine\SqlFormatter\SqlFormatter;

echo (new SqlFormatter(new NullHighlighter()))->format($query);
```

The README's stated use for this is outputting to error logs or other non-HTML formats, which is the right framing. A log line with `<span class="hljs-keyword">` in it is worse than no highlighting.

The automatic behaviour is the part worth knowing before you deploy. The README says that when you run PHP under CLI and instantiate `SqlFormatter` without an argument, it highlights with `CliHighlighter`. Otherwise you get an HTML highlighter such as `HtmlHighlighter`. The constructor takes `Highlighter` implementations, and the classes `HtmlHighlighter` and `CliHighlighter` are the ones the README names.

So the same call site produces HTML in a web request and ANSI-coloured terminal output in a cron job. That is helpful behaviour and also a latent bug source: if you format a query once at startup and cache the string, you have cached whichever format was current at that moment.

Pass the highlighter explicitly in shared code. The cost is one argument.

## Three methods, and only one adds line breaks

The three methods differ in more than degree, and picking the wrong one wastes the work.

`format` does both: it indents, adds line breaks and highlights. This is the one you want for a debug view of a query that has arrived as a single line.

`highlight` preserves all original whitespace and only adds syntax highlighting. The README describes it as useful for SQL that is already well formatted and just needs to be a little easier to read. This is the method that surprises people: they reach for it expecting formatting and get a single long line with coloured tokens.

`compress` goes the other way. It removes all comments and compresses whitespace. The README's example makes the comment handling visible:

```sql
-- This is a comment
    SELECT
    /* This is another comment
    On more than one line */
    Id #This is one final comment
    as temp, DateCreated as Created FROM MyTable;
```

which compresses to:

```sql
SELECT Id as temp, DateCreated as Created FROM MyTable;
```

Note that three different comment syntaxes are handled: `--` line comments, block comments spanning lines, and the MySQL-specific `#`. That is the kind of detail that suggests the tokeniser is keyword and punctuation driven rather than a full grammar, which matters if you feed it dialect-specific SQL.

The stated use for `compress` is producing queries you can paste onto a command line. That is a real workflow: read a slow query log entry, paste it into a client, run it.

All three are static-in-effect methods on an instance, and all three return a string rather than writing anywhere.

## A doctrine-namespaced package with a small maintenance gap

The repository is small and conventional for a PHP library: `src/`, `tests/`, `examples/`, `bin/`, a `composer.json`, and three dot-dist config files that name the tooling. `phpcs.xml.dist` is the coding standard, `phpstan.neon.dist` is the static analysis config, and `phpunit.xml.dist` is the test configuration. Having all three configured rather than none is a decent signal about the project's habits.

The examples directory carries four entries, of which two are illustrative: `readme_format_html.svg` and `readme_highlight_html.svg` are the rendered output of the `format` and `highlight` calls that the README embeds as images rather than as text. That is a documentation choice worth noting: you cannot read the highlighted output as text in the README, you have to look at it. The plain-text `format` output *is* shown as a fenced block, which is why the `NullHighlighter` example is the one you can actually check.

There are also `examples/cli.php` and `examples/examples.php`, so the CLI highlighter behaviour can be tried locally.

The default branch is `1.5.x`, not `main`, which tells you the project develops on a release line rather than on a trunk. Recent tags are 1.5.4 from 2026-02-08, 1.5.3 from 2025-10-26 and 1.5.2 from 2025-01-24. The last push was on 2026-06-11 and the repository is not archived, so it is receiving work,.

Licence is MIT, in `LICENSE.txt`.

## Where it is the wrong tool

The clearest wrong case is expecting a SQL parser. Nothing here reads SQL. `compress` and `format` both work by tokenising enough to find keywords, punctuation and comments, and the README says nothing about dialects, reserved word lists or parameter placeholders. Feed it a statement with dialect-specific syntax you have not seen before and the indentation will be wrong rather than an error. For a debugging view that is acceptable; for anything that must be correct, it is not.

The second wrong case is SQL containing secrets, formatted into HTML. Highlighting wraps tokens in markup, which means whatever escaping happens is the highlighter's job. The README does not discuss HTML escaping of string literals in the formatted output, so before rendering formatted SQL containing literal values on an admin page, check the escaping behaviour yourself.

The third is the automatic highlighter choice, described above. Code that formats in both a web request and a CLI process with a cached result will produce the wrong format for one of them.

What the README does not document is worth stating plainly: no PHP version requirement, no dialect coverage, no thread or reentrancy notes, and no statement about how the formatter treats placeholders like `?`, `:name` or `$1`. If you are formatting a parameterised query for a log, that is the first thing to test.

## Conclusion

Adopt doctrine/sql-formatter when you need readable SQL in a debug page, an exception message or a log, and you want highlighting and indentation from an MIT package with no configuration file. Do not adopt it as a SQL pretty-printer that rewrites queries: `compress` strips comments and whitespace but does not parse SQL, and the README does not describe dialect support, so a formatter is not a parser. Before wiring it into an error page, decide which of the three methods you actually want, and pass an explicit `NullHighlighter` for plain-text log output rather than relying on the constructor's automatic choice, which depends on whether PHP is running under CLI.

## FAQ

### How do I use Doctrine's sql-formatter in PHP?

Load the Composer autoloader with `require_once 'vendor/autoload.php'`, import `Doctrine\SqlFormatter\SqlFormatter`, and call `format` on an SQL string: `echo (new SqlFormatter())->format($query);`. There is no configuration file.

### How do I turn off syntax highlighting in sql-formatter?

Pass a NullHighlighter as the constructor argument, for example `new SqlFormatter(new NullHighlighter())`. The README positions this for error logs and other non-HTML output. Without an argument, the formatter picks CliHighlighter when running under CLI and an HTML highlighter otherwise.

### What is the difference between format, highlight and compress?

format indents, adds line breaks and highlights. highlight preserves all original whitespace and only adds highlighting, for SQL that is already well formatted. compress removes all comments and compresses whitespace, producing a query you can paste onto a command line.

## Sources

- [doctrine/sql-formatter on GitHub](https://github.com/doctrine/sql-formatter)
- [Issues](https://github.com/doctrine/sql-formatter/issues)
- [License: MIT](https://github.com/doctrine/sql-formatter/blob/1.5.x/LICENSE)
- [README](https://github.com/doctrine/sql-formatter/blob/1.5.x/README.md)
- [Releases](https://github.com/doctrine/sql-formatter/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/doctrine-sql-formatter
