PHP 8.6 arrives on November 19. DressCode already rewrites code for it. 16 days Upgrading to a newer PHP →

PHP code style fixer and upgrader

Same code.
Just better.

DressCode checks and fixes code against your coding standard, rewrites it for PHP 8.4, 8.5 and 8.6, and migrates it to the latest APIs of Nette, Symfony and Laravel. It works on a lossless syntax tree, so whatever it does not fix stays exactly as you wrote it, byte for byte. One tool, one configuration, one diff.

composer global require dresscode/dresscode
dresscode init
dresscode fix
  • Upgrades code for
  • php
  • Nette
  • Symfony
  • Laravel
class Cart {
    function add( Item $item ){
        if($item->price==null) return;
        $this->items[]=array("name"=>$item->name,"price"=>$item->price);
    }
}
class Cart
{
    public function add(Item $item)
    {
        if ($item->price == null) {
            return;
        }
        $this->items[] = ["name" => $item->name, "price" => $item->price];
    }
}

dresscode fix with the perCs standard, PER Coding Style 3.1

Coding standards

PER Coding Style, PSR-12, Nette, Symfony and Laravel

PHP upgrades

To 8.4, 8.5 and 8.6

Framework upgrades

Nette, Symfony and Laravel

One configuration

Style, PHP and libraries in one file

How it works

One run, three jobs.

  1. Checks and fixes code against your coding standard

    Start from PER Coding Style 3.1, PSR-12, Nette, Symfony or Laravel, and tailor anything you want changed, key by key.

    if($user==null) return;
    
    if ($user == null) {
        return;
    }
    
    Standards and sets →
  2. Rewrites your code for a newer PHP

    Raise the version in composer.json, run fix, and the diff is the code you would have written for the new version yourself.

    return trim(strtolower(strip_tags($title)));
    
    return $title |> strip_tags(...) |> strtolower(...) |> trim(...);
    
    Upgrading to a newer PHP →
  3. Upgrades your libraries

    dresscode upgrade measures what a move to a newer Nette, Symfony or Laravel takes, plans it and carries it out with Composer and your tests, in the style your code already has.

    $request = $this->requestStack->getMasterRequest();
    
    $request = $this->requestStack->getMainRequest();
    
    Upgrade step by step →
$ dresscode init
DRESS|CODE 1.4.0
Project    29 PHP files in src, tracy/tracy
PHP        8.2 and newer, from `composer.json`
Standard   nette, the nearest to your code, …
Measured   your code departs from it in 17 decisions, …
Checked    a fix changes 1 file, …
Written    `dresscode.neon`

$ dresscode check
src/Tracy/Dumper/Exposer.php
  error  120:7  The variable `this_` must be written in camelCase.
…
FOUND  7 violations, a fix leaves 2 in 3 of 29 files

$ dresscode fix
FIXED  7 violations found, 2 remaining in 3 of 29 files

The first run on the Tracy codebase, 29 files: init measures the code and writes down the style it already has, so the first check finds only 7 violations.

118 msa small file, checked after every save
436decisions you can set key by key
5standards: perCs, psr12, nette, symfony, laravel
MITopen source, no telemetry

Configuration

A configuration that describes your code

use:
	- perCs
	- modernizations

braces:
	position:
		class: nextLine
spacing:
	concatenation: '$a.$b'
qualification:
	function:
		global: bare
		optimized: imported

You can read it out loud: the brace of a class goes on the next line, the concatenation dot has no spaces around it, global functions are written as bare names, and the ones PHP optimizes are imported.

PHP CS Fixer has no single setting for what the last two lines say. The result comes from two rules acting together, and you have to work it out:

'native_function_invocation' => [
	'include' => ['@compiler_optimized'],
	'scope' => 'namespaced',
	'strict' => true,
],
'global_namespace_import' => ['import_functions' => true],

The standard says what the code looks like. The sets say what you want from it besides its looks. Anything else is one key.

All the keys in the configuration reference →

Under the hood

Why it can do that.

A tree with everything in it

An AST throws away whitespace and comments. DressCode is built on a lossless syntax tree, PhpSyntax: printed back, it reproduces the original file byte for byte. So only what a rule touched changes.

A rule reads like a sentence

The heart of the rule that shortens $a ? $a : $b to $a ?: $b. Its whole file has 96 lines and works both ways: it can also write the ternary in full. The fixer in PHP CS Fixer that only shortens it has 223 lines and is marked risky.

public function enter(Node|Token $node, RuleContext $context): void
{
	if (
		!$node instanceof TernaryNode
		|| $node->then === null
		|| !$node->condition->isRepeatableRead()
		|| !$node->condition->matches($node->then)
		|| $node->question->getCurrentLine() !== $node->colon->getCurrentLine()
		|| $node->question->hasCommentUpTo($node->colon)
		|| !$context->report($node, 'The ternary repeating its condition must be written `?:`.')
	) {
		return;
	}

	$node->then = null;
	$node->question->setTrailingTrivia([]);
}
Write your own rule →

No priorities

All rules run in one pass, again and again until the code stops changing. When two of them disagree, the engine notices and says which.

Risk belongs to the place, not the rule

switch becomes match where the types show that integers or enum cases are compared; elsewhere it is only reported. The types come from your project's PHPStan.

Speed

Measured, not claimed.

WhatDressCodeCounterpart
One small file, checked after every save118 msPHP CS Fixer 323 ms
Symfony with its own configuration, 7,704 files14.2 sPHP CS Fixer 25.3 s
Rewrite for a newer PHP, Symfony 3.41.6 sRector 128.5 s
PER Coding Style fix of Laravel, 1,696 files: places the other tool still finds9PHP CS Fixer 1,201

For reporting alone, phpcs is faster: dresscode check computes the fixes in memory even when it only checks. Measured in October 2026 on PHP 8.5 against PHP CS Fixer 3.95, PHP_CodeSniffer 4.0 and Rector 2.6, median of three runs. How DressCode works →

AI agents

Made for code that agents write

Install the php-fixer plugin in Claude Code, and after every edit to a PHP file DressCode fixes it and tells the agent in plain sentences what changed.

/plugin marketplace add nette/agent-plugins
/plugin install php-fixer@nette

For a clean file it prints nothing, so the check costs the agent no context.

AI agents →

DressCode changed `src/Cart.php`; the changes below are already in the file:

- removed the import of `Acme\Shop\Payment\Gateway`: nothing used it; if you meant to use it, add the import in the same edit as the use.

@@ -12,7 +10,7 @@
 	public function add(string $name, int $price): void
 	{
-		$this->items[] = ["name" => $name, "price" => $price];
+		$this->items[] = ['name' => $name, 'price' => $price];
 	}

Get going

Start where you are.

The story

Why it exists.

One rule in my coding standard had grown to 947 lines over an array of tokens, and it needed four fixes in one summer. I wanted to know why a rule has to be that complicated. The answer grew into two projects: a PHP parser that keeps every byte, and a tool built on it.

David Grudl, author of Nette

Checks the code of

  • Nette
  • Latte
  • Tracy
  • Nette Tester
  • PhpSyntax
  • this site

One tool, one configuration, one diff.