PHP 8.6 vychází 19. listopadu. DressCode pro něj kód přepisuje už teď. 15 dní Přechod na novější PHP →

Začínáme s DressCode

DressCode nainstalujete během minuty a můžete si ho nanečisto vyzkoušet na vlastním projektu, aniž by sáhl na jediný soubor. Hned uvidíte, kde se váš kód odchyluje od zvoleného standardu (například PER Coding Style 3.1 či Nette), co přesně by automatická oprava změnila a jaké výhody by vám přinesla novější verze PHP. Formátování stylu i modernizaci na novější PHP a knihovny přitom DressCode zvládne v jediném průchodu.

Instalace

DressCode je samostatný nástroj, nikoliv knihovna, takže ho můžete mít nainstalovaný úplně mimo projekt, který zrovna kontroluje. Nejjednodušší cestou je globální instalace přes Composer:

composer global require dresscode/dresscode

Adresář s globálními binárkami Composeru si přidejte do systémové proměnné PATH a příkaz dresscode pak spustíte odkudkoliv.

V prostředí průběžné integrace (CI), kde potřebujete mít verzi nástroje pevně uzamčenou, se hodí instalace do samostatné složky:

composer create-project dresscode/dresscode temp/dresscode
temp/dresscode/bin/dresscode check

A do třetice: DressCode můžete přidat přímo do projektu jako vývojovou závislost (composer require --dev dresscode/dresscode) a spouštět z vendor/bin/dresscode. Tuto variantu zvolte ve chvíli, kdy v projektu používáte také PHPStan. DressCode se ho pak přímo ptá na typy ve vašem kódu a dokáže díky tomu spolehlivě přepsat zastaralé API knihoven podle reálného typu proměnné (více na stránce Typy z PHPStanu). Počítejte jen s tím, že samotný DressCode vyžaduje PHP 8.4 až 8.6, takže na některé z těchto verzí musí běžet i prostředí vašeho projektu – i kdyby kód samotný cílil na starší PHP.

Tohle bývá nejčastější zdroj nedorozumění: verze PHP, na které běží samotný DressCode, a cílová verze PHP vašeho kódu jsou dvě zcela nezávislé věci. Když máte DressCode nainstalovaný globálně nebo mimo projekt, může bez problémů běžet na PHP 8.5 a přitom kontrolovat kód psaný pro PHP 8.1. Cílovou verzi si sám vyčte ze sekce require.php v composer.json vašeho projektu a striktně se jí drží, takže vám do kódu nikdy nevloží syntaxi, které by cílové PHP nerozumělo. Podporovány jsou všechny verze od PHP 8.0 výše; starší verze PHP DressCode nepodporuje a při pokusu o jejich použití vás na to upozorní.

DressCode je postavený minimalisticky: parser a bezztrátový syntaktický strom, na kterých vše stojí, tvoří samostatná knihovna PhpSyntax bez jakýchkoliv externích závislostí. K tomu využívá jen čtyři drobné balíčky z Nette, parser phpDocu z PHPStanu a porovnávač verzí z Composeru. Žádný robustní framework.

Co chcete udělat?

DressCode zastane hned několik různých úkolů a pro každý z nich nabízí podrobného průvodce. Zvolte si cestu podle toho, co zrovna řešíte:

Pokud si ale chcete nástroj nejdřív oťukat v praxi, nikam neodcházejte. V následujících krocích spustíte na svém kódu tři příkazy a žádný z nich nezmění ani bajt.

Kontrola PHP kódu bez jediné změny

DressCode nemá žádný svůj vlastní dogma-styl, a proto se bez konfigurace záměrně nespustí. Kdyby totiž potichu vybral některý ze standardů, první fix by vám v jinak formátovaném projektu přepsal prakticky každý řádek. Pro rychlé vyzkoušení proto standard zvolte přepínačem --use a přidejte cesty ke složkám:

dresscode check src tests --use perCs

Výstup v terminálu vypadá takto:

DRESS|CODE 1.3.0
Config     none, using perCs
Target     PHP 8.2 from `composer.json`
Checking   214 files in /var/www/shop

src/Cart.php
  error   9:61  Expected a line break before the opening brace.         braces.position.function
  error  10:17  The array must be written `[…]` instead of `array(…)`.  literals.arraySyntax.array
  error  11:12  Expected no whitespace after the opening parenthesis.   spacing.padding.controlStructure
  error  11:20  Expected at least one space before the `==` operator.   spacing.binaryOperator
...

FOUND  36 violations, a fix leaves 1 in 12 of 214 files

Každý nález přesně říká, kde k porušení došlo (řádek a sloupec), co přesně je špatně (popis očekávaného stavu) a které konfigurační rozhodnutí kód porušuje. Cesta vpravo, například braces.position.function, je klíč konfigurace, se kterým můžete dál pracovat: nechat si ho vysvětlit i s povolenými hodnotami (dresscode explain braces.position.function), nastavit mu jinou hodnotu, vyhledat ho v katalogu pravidel nebo vypnout na jediném místě.

Hlavička výpisu odpovídá na dvě klíčové otázky, které jinak bývají zdrojem zbytečných nedorozumění: podle čeho se kontroluje (použitá konfigurace a presety) a pro jakou cílovou verzi PHP. Shrnutí na konci navíc prozradí, kolik nálezů by po automatickém spuštění fix v kódu ještě zůstalo.

Každé hlášení je srozumitelná celá věta vztažená ke konkrétnímu místu. Kdekoliv DressCode měří vzdálenosti či odsazení, přesně vyčíslí očekávanou i nalezenou hodnotu (Expected the statement indented by 12 spaces, 10 spaces found.). Pokud by oprava jedné chyby vyvolala chybu jinou, vypíše ji DressCode hned pod původním nálezem s označením Then also.

Skutečná síla těchto zpráv se projeví tam, kde jde o víc než jen o kosmetiku. Podívejte se na ukázku kontroly dvou souborů podle pravidel ze sekcí classes, mistakes a upgrading s využitím typů z PHPStanu:

src/Settings.php
  risky  7:37  The parameter `$name` of `offsetGet()` must be named `$key`, as in `ArrayObject::offsetGet()`.  classes.overridingMethod.parameterName
               Risky because a call naming the argument `name:` stops working.

src/Users.php
  error  12:16  The `in_array()` call must pass `$strict = true`.                    mistakes.strictArgument
  risky  17:16  The `in_array()` call must pass `$strict = true`.                    mistakes.strictArgument
                Risky because a strict search no longer finds a value of another type.
  error  22:18  Method `Acme\Mail\Mailer::sendMessage()` is deprecated: use send().  upgrading.declarations.deprecatedMember

Třída Settings přepisuje metodu offsetGet() rodičovské třídy ArrayObject, ale její parametr pojmenovala $name. Samotné PHP to sice povolí, jenže volání $settings->offsetGet(key: 'theme'), které u každého ArrayObject bez problémů funguje, náhle zhavaruje s chybou Unknown named parameter $key. Automatické přejmenování parametru by ale zase rozbilo volání, která už začala používat pojmenovaný argument name:. Jde tedy o rizikovou opravu (risky fix), která může změnit chování programu. Nález proto přesně vysvětluje, co konkrétního hrozí.

Ačkoliv obě volání in_array() dostala stejnou zprávu, oprava se k nim zachová zcela odlišně. Na řádku 12 typová analýza potvrdila, že se hledá int v poli typu list<int>; striktní porovnání zde vrátí stejný výsledek, takže fix doplní parametr true zcela bezpečně a automaticky. Na řádku 17 je však prohledávaná hodnota obecného typu mixed: taková oprava počká, dokud ji výslovně nepovolíte, a do té doby vás pouze informuje, co by změnila.

Metodu sendMessage() označila knihovna anotací @deprecated use send(). Nález toto doporučení cituje a automatický fix kód rovnou přepíše na send().

Návratový kód (exit code) je 0, pokud je kód zcela čistý, a 1, jakmile narazí na jakýkoliv nález. Stejný příkaz tak můžete okamžitě nasadit do průběžné integrace. Přehled všech čtyř exit kódů najdete v referenci příkazové řádky.

Oprava, než se stane

Přidejte přepínač --diff a kontrola vám pod nálezy každého souboru rovnou ukáže přesný diff, který by vygeneroval příkaz fix:

dresscode check src tests --use perCs --diff
--- src/Cart.php
+++ src/Cart.php
@@ -6,9 +6,10 @@

 class Cart
 {
-    public function add(Product $product, int $count): void {
-        $line = array($product, $count);
-        if ( $count== 0) {
+    public function add(Product $product, int $count): void
+    {
+        $line = [$product, $count];
+        if ($count == 0) {
             return;
         }
         $this->lines[] = $line;

Do souborů se stále nic nezapisuje. Výsledný diff čtěte stejně jako pull request v code review: pokud upravuje věci, na kterých panuje v týmu shoda, je vybraný standard vašemu kódu velmi blízko. Pokud naopak přepisuje polovinu každého souboru, zjevně píšete v jiném stylu. Jiný standard můžete bleskově otestovat změnou jediného slova: --use psr12, --use nette, --use symfony nebo --use laravel.

Náhled upgradu na novější PHP

DressCode kód nejen formátuje, ale také modernizuje na novější verze PHP. Stará se o to sada modernizations, kterou si můžete vyzkoušet i samostatně bez standardu, aby diff ukázal čistě jen syntaktické přepisy:

dresscode check src --use modernizations --diff
return $article === null ? null : $article->getAuthor();
return $article?->getAuthor();

Cílovou verzi PHP si sada přečte ze sekce require.php v composer.json a nabídne jen ty konstrukce, které daná verze reálně podporuje. Zkuste ji zvednout, spusťte příkaz znovu a hned uvidíte, jaké moderní prvky může váš kód okamžitě využít. Takhle můžete postupovat od PHP 8.0 až po PHP 8.6. Všechny možnosti přepisů a praktický postup popisuje stránka Přechod na novější PHP.

Když chcete zapisovat

Zápis do souborů provádí příkaz fix, a ani ten bez konfigurace nezačne. Volba --use perCs z vaší zkoušky se nikam neuložila, takže samotný příkaz dresscode fix skončí s chybou a exit kódem 3:

Error: No `dresscode.neon` or `dresscode.php` found in `/var/www/shop` or above it, so there is no dress code to check against. Run `dresscode init` to have one made to measure from the code, or name a standard with `--use`.

Mohli byste sice přepínač --use perCs zopakovat a nechat DressCode zapsat vše, co ukázal diff. Jenže v projektu s vlastním zavedeným stylem by to znamenalo obří nepřehledný diff, který v týmu nikdo neschválí. Daleko lepším prvním krokem je příkaz dresscode init: ten detailně zanalyzuje váš stávající kód, vybere k němu nejbližší standard, do dresscode.neon uloží jen reálné odchylky vašeho projektu a první automatickou opravu udrží v bezpečném rozsahu několika málo souborů. Celý proces vás provede stránka Formátování kódu krok za krokem – od úvodního měření až po pravidla hlídaná v CI.

Jediným příkazem, který do souborů zapisuje i bez konfiguračního souboru, je dresscode upgrade today. Ten po aktualizaci knihoven v Composeru přepíše kód na jejich nové API a může si to dovolit proto, že formátování a styl nechává zcela netknuté (více na stránce Upgrade kódu krok za krokem).

Kam dál

Zobrazit na GitHubu · Nahlásit problém se stránkou na GitHubu · 2. 11. 2026