Slovník pojmů

PHPStan

PHPStan kontroluje typové kontrakty a možné chyby ještě před spuštěním scénáře. V PHP projektu tak doplňuje testy, coding standards i běžný syntax lint.

Stručná definice

Analyzátor, který rozumí typům a toku PHP kódu.

Obecné heslo Statická analýza kódu vysvětluje princip. PHPStan je jeho konkrétní implementace pro PHP: pracuje s nativními typy, PHPDoc, Composer autoloadingem a konfigurací projektu. Z nich vyvozuje, jaké hodnoty mohou na dané místo přijít a zda s nimi kód zachází bezpečně.

Nástroj aplikaci nespouští ani neověřuje, zda obchodní pravidlo odpovídá zadání. Odhaluje ale například volání metody nad nullable hodnotou, chybný typ argumentu, neexistující symbol, neplatný návratový typ, neúplně popsanou kolekci nebo část nedosažitelného kódu.

Použití

Kdy PHPStan přináší nejvíc zpětné vazby

Nejlépe funguje tam, kde jsou kontrakty popsané přesně a kontrola běží při každé změně.

  • refaktoring rozhraní, DTO, repository a aplikačních služeb
  • kontrola nullable hodnot, návratových typů a typů argumentů
  • popis kolekcí a generických pomocných tříd pomocí PHPDoc
  • zpřesnění dynamických částí frameworku pomocí rozšíření nebo stubů
  • automatická kontrola pull requestu v CI před sloučením změny

Praktický příklad

Kód, který PHP spustí, ale zákazník nemusí existovat

Metoda repository oprávněně vrací ?Customer, protože pro externí ID nemusí být záznam uložený. Pokud aplikační služba bez kontroly čte e-mail, při nalezeném zákazníkovi poběží, ale při chybějícím skončí chybou. PHPStan upozorní na možné volání metody nad Customer|null ještě před spuštěním importu.

Oprava musí vyjádřit obchodní rozhodnutí: zákazníka vytvořit, import označit jako neúplný, nebo použít metodu s kontraktem konkrétní výjimky. Samotná analýza toto rozhodnutí nenahradí.

final class ImportOrder
{
    public function __construct(private CustomerRepository $customers) {}

    public function customerEmail(string $externalId): string
    {
        $customer = $this->customers->findByExternalId($externalId); // ?Customer

        return $customer->email(); // PHPStan: Customer|null
    }
}

Jak funguje

Od zdrojových souborů k nálezu

Přesnost výsledku závisí na kvalitě typových informací, ne jen na zvolené úrovni.

  1. Konfigurace Soubor phpstan.neon určí analyzované cesty, úroveň pravidel, include soubory a nastavení projektu.
  2. Symboly a metadata PHPStan načte známé třídy a funkce přes Composer, nativní typy, PHPDoc a případná rozšíření frameworku.
  3. Odvození typů Při průchodu větvemi sleduje možné hodnoty proměnných, návraty metod a platnost operací.
  4. Diagnostika Nález uvádí soubor, řádek a identifikátor chyby, aby jej šlo opravit nebo výjimečně zdůvodněně ignorovat.
  5. CI Stejný příkaz v pull requestu zastaví změnu, která přidá nový porušený kontrakt.

Co PHPStan kontroluje

Typové informace nad rámec běžného běhu PHP

Jde o kontrolu technických kontraktů. Nejde o formátování zdrojových souborů ani spuštění testovacích scénářů.

Nativní a odvozené typy

Vyhodnocuje parametry, návraty, vlastnosti, union a nullable typy i typy vzniklé po podmínkách.

PHPDoc a generika

Typové zápisy PHPDoc, například array<int, Order>, a tagy jako @template nebo @extends zachovají informaci o prvcích kolekce, kterou PHP v array nevyjádří.

Type aliases

Složitější opakovaný tvar dat lze pojmenovat aliasem, aby kontrakt DTO nebo pole zůstal čitelný a jednotný.

Úrovně přísnosti

Úrovně jsou kumulativní; max označuje nejvyšší úroveň daného vydání. Vyšší přísnost odhalí více rizik, ale vyžaduje přesnější typy.

Rozšíření a vlastní pravidla

Rozšíření pro Symfony, Doctrine, Nette, PHPUnit nebo Larastan zpřesní dynamické chování. Vlastní rule lze přidat pro opakovaně nechtěný vzor specifický pro projekt.

Jasné hranice nástrojů

Každý nástroj zachycuje jiný druh problému

Slučovat jejich odpovědnosti by vedlo k falešnému pocitu pokrytí.

Statická analýza
PHPStan je konkrétní analyzátor; obecné heslo popisuje princip nezávisle na produktu.
PHPUnit
PHPUnit spouští připravené testy. PHPStan žádný scénář nespouští; může najít chybu i v nevolané větvi.
PHP_CodeSniffer
PHPCS kontroluje coding standards, například mezery, importy nebo týmové konvence. Nevyhodnocuje běžně možné typy hodnot.
Syntax lint
php -l ověří, že parser soubor přijme. Neodhalí většinu chyb kontraktů mezi třídami.
Formátování
Automatický formátovač upraví zápis kódu. PHPStan kód nepřepisuje a neřeší estetickou podobu souboru.

Výhody a omezení

Důležitá kontrola, nikoli důkaz správnosti aplikace

Přínosy

  • rychlá zpětná vazba před běžným spuštěním aplikace
  • bezpečnější refaktoring díky dohledání závislých kontraktů
  • přesnější typy pomáhají také IDE a dalším lidem v týmu
  • opakovatelná kontrola v CI nezávislá na pozornosti při code review

Omezení a chyby

  • statická analýza nenahradí unit, integrační ani end-to-end test
  • příliš obecné mixed a neúplný PHPDoc snižují hodnotu výsledku
  • nejvyšší úroveň sama nezaručí dobrý doménový návrh
  • globální ignore nebo bezmyšlenkovitě rostoucí baseline mohou skrýt nové chyby

Konfigurace a zavádění

Přísnost má odpovídat schopnosti nálezy opravovat.

Konfigurace obvykle obsahuje analyzované cesty, úroveň a include soubory pro rozšíření. U nového projektu dává smysl nastavit ambiciózní úroveň a držet výsledek bez chyb. U starší aplikace lze přísnost navyšovat postupně, pokud tým rozumí tomu, co konkrétní nálezy znamenají.

Baseline dočasně potlačí známé existující nálezy a dovolí blokovat nové. Nemá se ale automaticky znovu generovat při každém běhu: ztratila by roli řízeného technického dluhu. Jednotlivou legitimní výjimku je vhodnější ignorovat přes identifikátor chyby, v úzkém rozsahu a s vysvětlením.

Praktická pravidla

Jak z kontroly získat skutečnou hodnotu

Cílem není co nejvyšší číslo v konfiguraci, ale důvěryhodné kontrakty a rychlé nalezení nových regresí.

  • nejprve opravit kontrakt u zdroje dat místo opakovaných inline @var
  • používat nativní typy a PHPDoc pro kolekce či generika
  • zvolit a aktualizovat jen relevantní frameworková rozšíření
  • držet baseline i ignoreErrors malé, konkrétní a zdůvodněné
  • spouštět stejnou konfiguraci lokálně i v CI

Časté otázky

Co od PHPStanu očekávat

Nahrazuje PHPStan PHPUnit?

Ne. PHPStan analyzuje kód bez spuštění scénáře. PHPUnit spouští testy a ověřuje konkrétní očekávané chování, včetně spolupráce komponent podle zvoleného typu testu.

Je PHPStan totéž co PHP_CodeSniffer?

Ne. PHP_CodeSniffer kontroluje coding standards a část nálezů umí opravit přes PHPCBF. PHPStan vyhodnocuje typové kontrakty a možné technické chyby; kód s perfektním stylem může mít stále chybný typ.

Má projekt vždy používat level max?

Je to rozumná volba, pokud tým umí udržet výsledek bez nových chyb a aktualizace nástroje. U starší aplikace může být lepší postupné navyšování úrovní nebo dočasná řízená baseline.

Kdy je vhodné chybu ignorovat?

Jen pro konkrétní zdůvodněnou výjimku, například nepopisovatelné dynamické chování třetí strany. Přednost má oprava typu u zdroje dat, stub, rozšíření nebo přesnější kontrakt.

Jak PHPStan používám v praxi

Typové kontrakty kontroluji vedle testů a architektury.

PHPStan na nejvyšší úrovni se strict rules používám jako součást běžné zpětné vazby při vývoji PHP aplikací.

Zavolejte mi

Zavolám vám následující pracovní den mezi 9:00 a 17:00.

Můžete mi také zavolat rovnou.

+420 605 181 728

Nechte mi telefonní číslo a pošlete žádost o zpětné zavolání.

Odesláním souhlasíte se zpracováním údajů pro vyřízení žádosti.