Nette Coding Standard
Chcete, aby váš PHP kód dodržoval Nette coding standard, a přitom sami nehlídat tabulátory, závorky a prázdné řádky? DressCode za vás projde každý soubor a co najde, opraví jediným příkazem.
DressCode je nová generace původního balíčku nette/coding-standard. Nette coding standard v něm najdete
vestavěný pod jménem nette. Mění jen to, co standard porušuje, a zbytek souboru nechá přesně tak, jak byl,
takže v diffu po opravě najdete opravy a nic jiného.
Instalace
DressCode nainstalujte globálně pomocí Composeru:
composer global require dresscode/dresscode
a ujistěte se, že váš globální adresář vendor/bin je v proměnné prostředí $PATH.
Samotný DressCode běží na PHP 8.4 až 8.6. To je ale PHP nástroje, ne PHP, pro které píšete kód: váš projekt
může cílit na kteroukoliv verzi od PHP 8.0. DressCode ji vyčte z položky php v sekci require
souboru composer.json vašeho projektu a nikdy nenapíše syntaxi, kterou tahle verze nezná.
Konfigurace
DressCode nemá žádný vlastní styl, takže mu nejdřív řeknete, jaký standard váš projekt dodržuje. Do kořene
projektu vložte soubor dresscode.neon:
use:
- nette
paths:
- app
- tests
Klíč use vybírá standard, paths vyjmenovává adresáře ke kontrole. Soubor commitněte, ať
kód kontroluje stejně celý tým i vaše CI.
Použití
Vyzkoušíme to na třídě napsané ve spěchu, app/Model/CartService.php, odsazené mezerami a se závorkami na
špatných řádcích:
<?php
declare(strict_types=1);
namespace App\Model;
class CartService {
public function getTotal(array $items): float {
$total = 0;
foreach ($items as $item) {
$total = $total + $item['price'] * $item['quantity'];
}
return $total;
}
}
Příkaz check vypíše, co standard porušuje, a nic nemění:
dresscode check
app/Model/CartService.php
error 1 `declare(strict_types=1)` must be on the line of the opening tag. file.strictTypes.position
error 2 Expected 1 blank line before the namespace, 2 found. blankLines.beforeNamespace
error 6 Expected 2 blank lines before the class, 1 found. blankLines.beforeDeclaration
error 7:19 Expected a line break before the opening brace. braces.position.class
error 8 Expected the member indented by 1 tab, 4 spaces found. indentation.unit
Then also, on lines 9, 10, 13: Expected the statement indented by 2 tabs, 8 spaces found. indentation.unit
Then also, on line 11: Expected the statement indented by 3 tabs, 12 spaces found. indentation.unit
Then also, on line 12: Expected the closing brace indented by 2 tabs, 8 spaces found. indentation.unit
Then also, on line 14: Expected the closing brace indented by 1 tab, 4 spaces found. indentation.unit
error 8:51 Expected a line break before the opening brace. braces.position.function
error 11:13 The assignment must be written `+=` instead of repeating its target. expressions.assignment.targetInValue
FOUND 13 violations, 6 of them following from others, a fix leaves none in 1 file
U každého nálezu je řádek (a sloupec), popis chyby a na konci jméno nastavení, které porušuje, třeba
braces.position.class. To jméno budete potřebovat, až budete chtít standard upravit. Řádky začínající
Then also patří k nálezu nad nimi, jsou to jeho důsledky. Příkaz fix pak opraví všechno,
co jde:
dresscode fix
A třída teď vypadá takhle:
<?php declare(strict_types=1);
namespace App\Model;
class CartService
{
public function getTotal(array $items): float
{
$total = 0;
foreach ($items as $item) {
$total += $item['price'] * $item['quantity'];
}
return $total;
}
}
Než poprvé spustíte fix, zazálohujte si soubory, nebo ho pusťte nad čistým pracovním stromem, ať můžete
změny potom projít přes git diff.
Úprava standardu
Každé nastavení standardu je klíčem konfigurace a poslední slovo u každého z nich má váš
dresscode.neon. Řekněme, že váš projekt chce mezi metodami jeden prázdný řádek místo dvou a nechce, aby se
== přepisovalo na ===:
blankLines:
aroundMethods: 1
expressions:
comparison:
loose: keep
Hodnota keep znamená „nech to tak, jak to má kód“. K čemu klíč slouží a jakou hodnotu má ve vašem
projektu, vypíše dresscode explain blankLines.aroundMethods. A když má jeden řádek dobrý důvod standard
porušit, připište k němu komentář // dresscode:ignore.
Novější PHP a Nette
DressCode umí víc než formátovat. Přidejte vedle standardu sadu modernizations a přepíše kód na to, co
nabízí novější PHP, třeba $user === null ? null : $user->getName() na $user?->getName(). Jde
přitom jen tak daleko, jak dovolí váš composer.json:
use:
- nette
- modernizations
Když aktualizujete knihovny Nette, balíček dresscode/upgrade-nette přepíše váš kód na jejich nové API,
viz Upgrade Nette.
Continuous Integration
V CI nainstalujte DressCode jako samostatný projekt, ať máte pod kontrolou, která verze poběží:
- run: composer create-project dresscode/dresscode temp/dresscode ^1
- run: php temp/dresscode/bin/dresscode check
Když check najde prohřešek, skončí s kódem 1 a build selže. V GitHub Actions se nálezy
zobrazí jako anotace přímo v pull requestu.
Přechod z verze 3
Původní balíček nette/coding-standard kontroloval standard pomocí PHP CS Fixeru a PHP CodeSnifferu, přes
příkaz ecs a soubory ncs.php a ncs.xml. Jeho vývoj skončil, nahradil ho DressCode, a
verze 3 je poslední. Při přechodu vytvořte dresscode.neon podle návodu výše, úpravy, které jste měli v
ncs.php a ncs.xml, zapište jako jeho klíče a oba soubory smažte. Všechny klíče i s hodnotami,
které mají ve vašem projektu, vypíše dresscode config.
První dresscode fix nejspíš sáhne na víc souborů, než čekáte, protože DressCode opravuje i některá
místa, která verze 3 nechávala být. Udělejte z něj samostatný commit bez dalších změn.
Všechno ostatní, od všech nastavení až po spouštění DressCode v editoru nebo po každé úpravě, kterou udělá AI agent, najdete v manuálu DressCode.