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:
- Coding standard pro existující projekt: Formátování kódu krok
za krokem vás provede od prvního spuštění
dresscode initaž po standard, který za vás automaticky hlídá CI. - Novější verze PHP: Přechod na novější PHP ukáže, jak kód psaný pro PHP 8.0 a novější elegantně přepsat tak, aby využíval novinky každé další verze až po PHP 8.6.
- Nové verze knihoven: Upgrade kódu krok za krokem vás provede odhadem pracnosti, sestavením plánu i samotným upgradem. Pro Nette, Symfony, Laravel i Dibi a Texy má DressCode detailní data o všech změnách mezi verzemi.
- Přechod z jiného nástroje: Přechod na DressCode krok za krokem předvede, jak snadno převést konfiguraci z PHP CS Fixeru, PHP_CodeSnifferu nebo Laravel Pintu.
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
- Formátování kódu krok za krokem, pokud chcete zavést coding standard do existujícího projektu a první commit udržet co nejmenší.
- Jak DressCode funguje, pokud vás zajímá vnitřní architektura a důvody, proč se nástroj chová právě takto.
- Upgrade kódu krok za krokem, Přechod na novější PHP a Typy z PHPStanu, pokud chcete kód nejen formátovat, ale i průběžně modernizovat.
- Přechod na DressCode krok za krokem, pokud dnes používáte PHP CS Fixer, PHP_CodeSniffer nebo Slevomat.
- Konfigurace, kompletní přehled možností konfiguračního souboru včetně vyzkoušení jednoho pravidla na jeden běh.
- Integrace, jak zapojit kontrolu stylu do CI, Git hooků, editoru nebo k AI agentům.