Čistý kód na starém projektu v PHP

Petr Kudyn
SUPERKODERS
Published in
6 min readOct 12, 2021

Někdo má rád jednorožce, někdo zase Star Trek. Ale jednu věc máme všichni společnou — chceme psát pěkný, čistý kód.

Co když ale dostanete na stůl několik let starý projekt? Navíc psaný ve starší verzi PHP (<7.4), který PHPStan neviděl ani z rychlíku, a který se má dál rozvíjet?

Zároveň také nemáte budget 300 hodin, abyste opravili všech 500 chyb, který vám PHPStan při první běhu vypsal… Dá se s tím vůbec něco dělat, nebo je to předem prohraná bitva?

No, tak zlé to zas nebude. Dáme hlavy dohromady a něco vymyslíme.

První pokusy

Hned na začátku si dovolím předpokládat, že používáte PhpStorm. Pokud ne, tak si ho můžete pořídit.

Pokud si ho koupit nechcete, protože už svůj oblíbený editor máte, nebo stále ještě píšete kód brkem na vlastnoručně vyráběný papír, tak mi nezbývá, než se s vámi rozloučit a popřát vám hodně štěstí. A my ostatní jdeme dál.

Jako první stojí za pokus využít všechny nástroje PhpStormu jako Code style, Code inspections, Before commit akce, atd (atd. je zde použito v klasickém smyslu — už nevím, co dalšího). Toto vám sice nějak zafunguje, ale má to své mouchy.

Začněme akcemi před commitem. Automatické formátování před commitem může za specifických podmínek vytvořit chybu v Latte šabloně. Přijde mi dobré vědět, co commituji a nespoléhat se, že tam něco magicky proběhne. Code analysis vám zase vygeneruje mračna chyb v nepřehledné tabulce. Od těchto akcí jsme tedy upustili.

Co se týče code style a code inspection, tak to není špatné a určité části z toho budeme i dále používat. Ale přeci jen cítíme, že PHPStan a CS je nepsaný standard. Navíc se dají pouštět dávkově, takže do budoucna do nějaké té CI/CD pipeliny bychom to chtěli už mít připravené.

PHPStan a CS

PHPStan je statický (= kód nepouští, pouze ho analyzuje) analyzátor kódu. Hlavní věc, kterou řeší, je typovost objektů. To, že PHP pracuje s typy velmi volně, bývá často zdrojem chyb a PHPStan se tyto potenciální chyby snaží najít. Umí toho ale mnohem víc. Pokud jste o něm ještě neslyšeli, mrkněte sem:

CS — tedy coding standard, je už spíše o způsobu, jakým kód formátujeme, aby se nám v něm dobře orientovalo. Takových nástrojů je na trhu více. My jsem si vybrali Ninjify z Contributte.

PHPStan a CS v Code inspection

Naštěstí tvůrci PhpStorm smýšlejí podobně a proto připravili integraci PHPStanu a CS do Code inspections. Můžeme tedy snadno a rychle vidět, co si PHPStan myslí o kódu, který právě píšeme. Starý kód zatím necháme ležet ladem a příležitostně ho vždycky upravíme, když půjdeme kolem.

A nyní už konkrétní návod, jak si to celé nastavit.

Krok 1 — instalace knihoven

Nejprve je třeba si do projektu přidat příslušné knihovny, a to konkrétně tyto:

composer require php-parallel-lint/php-parallel-lint — dev
composer require php-parallel-lint/php-console-highlighter — dev
composer require ninjify/coding-standard — dev
composer require phpstan/phpstan — dev
composer require phpstan/phpstan-deprecation-rules — dev
composer require phpstan/phpstan-strict-rules — dev
composer require phpstan/extension-installer — dev
// volitelná rozšíření pro phpstan — viz nížecomposer require phpstan/phpstan-nette — dev
composer require nextras/orm-phpstan — dev

Jak vidíte, jsou tam tři skupiny — Parallel lint, Coding standard a PHPStan.

Parallel lint je takový předskokan, který do Stormu integrovat nebudeme. Doporučuji si ho však nainstalovat a jednou dávkově spustit. Budete si pak jistí, že všechen ten starý kód neobsahuje žádné syntaktické chyby. Ano, i to se může stát. Pro snadné dávkové spouštění všech knihoven si můžete do composer.json přidat následující řádky (parametry si upravte podle struktury projektu):

"scripts": {
"phpstan": [
"phpstan analyse -c .phpstan.neon --memory-limit=2G"
],
"cs": [
"phpcs --standard=.ruleset.xml"
],
"lint" : [
"parallel-lint --blame app tests --exclude tests/var"
],
"cs-fix": [
"phpcbf --standard=.ruleset.xml"
]
}

Pak už stačí napsat do příkazové řádky např.: composer lint

Co se týče PHPStan rozšíření, tak u nich záleží, jaké knihovny používáte. V našem příkladu je tam rozšíření pro Nette a Nextras ORM a dále jsme si naložili i extra striktní pravidla (phpstan-strict-rules) a nakonec varování před používáním deprecated method/objektů (phpstan-deprecation-rules).

A aby nám fungoval extension-installer, který automaticky registruje PHPStan rozšíření, je třeba přidat do composer.json toto:

“extra”: {
“phpstan”: {
“includes”: [
“extension.neon”
]
}
}

Dále bude třeba trocha konfigurace:

.phpstan.neon
.phpstan-autoload.php
.ruleset.xml

Všechny soubory přijdou do rootu projektu.

  • .phpstan.neon je konfigurace PHPStanu, občas tam bude potřeba přidat nějakou výjimku — o tom ještě bude řeč.
  • .phpstan-autoload.php je autoloader pro PHPStan, zde udělán tou nejminimalističtější cestou ever použitím composer autoload. Lze upravit dle libosti.
  • .ruleset.xml je konfigurace CS, je tam pro ukázku vypnutá kontrola namespace (SlevomatCodingStandard.Files.TypeNameMatchesFileName) — což se u starších projektů, které prostory jmen nepoužívají, nebo je používají volně, může hodit. A dále je deaktivovaný požadavek na early exit (SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed).

Krok 2 — konfigurace PhpStormu

Poznámka na úvod: některá pravidla v CS/PhpStormu se mohou bít s code style/code inspections ve Stormu. Je tedy potřeba si to hlídat, a když taková situace nastane, tak příslušné pravidlo ve Stormu vypnout. Je také možné vypnout celé Code inspections.

Ve složce vendor/coding-standard/phpstorm najdete vyexportované doporučené nastavení Coding standardu pro PhpStorm, to si můžete naimportovat:

Doporučuji ještě vypnout zarovnání parametrů funkce, to se s CS trochu bije:

Případně to lze udělat i v souboru .editorconfig, pokud ho používáte:

[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
ij_php_align_multiline_parameters = false

A jedeme dál: v Settings > PHP > Quality tools si nastavíme PHP_CodeSniffer zhruba podle obrázku:

Tool process timeout doporučuji nastavit spíše větší, aby to zvládlo zpracovat i větší soubory.

Dále si v Settings > PHP > Quality tools nastavíme PHPStan:

A teď vše propojíme s Code inspections — Settings > Editor > Inspections > PHP > Quality tools. Doporučuji nastavení jako week warning, aby to tolik nerušilo. Coding standard si dejte Custom a vyberte si ten náš soubor .ruleset.xml.

A podobně PHPStan, zvolte si level — doporučuji 8 a také dostatečně velký memory limit, PHPStan je žrout paměti.

Závěr

Teď se můžete podívat, co všechno budete mít v editoru podtrhnuté a zkusit si s tím pohrát. Někdy příště si třeba řekneme tipy a triky, jak se s tím vším popasovat.

Pokud se vám článek líbil, pošlete mi třeba bitcoin. A pokud ne, tak si to nechte pro sebe. Na nějaké hejty není nikdo zvědavej, že jo…

Pokoj vám.

A pokud byste chtěli jít pracovat k Superkodérům, tak se ozvěte a přijďte pobejt. Je tu sranda.

--

--