Statická analýza PHP s knihovnou Phan

PHP

POZOR! Článek jsem napsal před více jak rokem, a tudíž už nemusí reflektovat můj nynější názor nebo může být zastaralý.

Jsem hrdý na to, kam to dopracovala knihovna PHPStan od Ondry Mirtese. Vždyť ji najdete i v tak známé Doctrine. Kromě PHPStanu, ale existuje i Phan, kterou vytvořil sám velký tvůrce PHP Rasmus Lerdorf v roce 2015 a je aktivně vyvíjená. Sice už moc ne panem Lerdorfem, který u projektu stál hlavně ze začátku, ale rozhodně neuškodí se na ni alespoň podívat. :)

Instalace

Jednoduše přes composer:

$ composer require phan/phan

Následně je nutné vytvořit konfigurační soubor, který si lze i vygenerovat:

$ ./vendor/bin/phan --init --init-level=3

Level 3 je středně striktní konfigurace. 1 je nejvíce striktní a 5 je nejméně.

Třeba mě ale stačí jednoduchý .phan/config.php:

<?php

return [
    'directory_list' => [
        'src',
        'vendor'
    ],

    'exclude_analysis_directory_list' => [
        'vendor/'
    ],
];

Potřebujete také nainstalovat PHP rozšíření php-ast. U mě na Windows to znamenalo pouze stažení dll knihovny a jeden řádek v php.ini:

extension=php_ast.dll

Když už jsme u php.ini, rovnou si vypněte xdebug, pokud ho máte zapnutý, jak Phan doporučuje.

$ ./vendor/bin/phan
[info] Disabling xdebug: Phan is around five times as slow when xdebug is enabled (xdebug only makes sense when debugging Phan itself)

Použití

Analýzu spustíte příkazem:

$ ./vendor/bin/phan

To vám vrátí výpis podobný tomuto (Nebo také ne, pokud je váš kód dokonalý :)):

src\Admin\Controller\AnswerController.php:12 PhanUnreferencedUseNormal Possibly zero references to use statement for classlike/namespace UploadedFileInterface (\Psr\Http\Message\UploadedFileInterface)
src\Admin\Controller\CreditMoveController.php:12 PhanUnreferencedUseNormal Possibly zero references to use statement for classlike/namespace UploadedFileInterface (\Psr\Http\Message\UploadedFileInterface)
src\Admin\Controller\HomepageController.php:46 PhanTypeMismatchArgument Argument 1 (params) is 'admin_homepage' but \Gephart\Routing\Router::redirectTo() takes array defined at vendor\gephart\routing\src\Router
.php:207

A s tím už se dá pracovat :)

Závěrem

Ve srovnání s PHPStanem mi výstup přijde nepřehledný pro lidské čtení:

$ ./vendor/bin/phpstan analyse -l 7 src

 ------ ------------------------------------------------------------------------------------------
  Line   Admin\Controller\AnswerController.php
 ------ ------------------------------------------------------------------------------------------
  48     Call to an undefined static method Gephart\Framework\Facade\Request::getParsedBody().
  49     Call to an undefined static method Gephart\Framework\Facade\Request::getUploadedFiles().
  55     Call to an undefined static method Gephart\Framework\Facade\EntityManager::save().
  57     Call to an undefined static method Gephart\Framework\Facade\Router::redirectTo().
  65     Call to an undefined static method Admin\Facade\AdminResponse::createResponse().
  79     Call to an undefined static method Gephart\Framework\Facade\Request::getParsedBody().
 ------ ------------------------------------------------------------------------------------------

Ale zase chápu, že pro následné parsování skriptem je to jednodušší.

Jako nevýhodu beru složitější instalaci a nutnost zásahu do php.ini, pokud knihovna php-ast už není nainstalovaná a aktivní. To mě upřímně téměř odradilo od vyzkoušení, ale dávám Phanu šanci a vyzkouším ho na pár projektech.

Znáte někoho, komu by článek mohl pomoct? Zasdílejte mu ho :)

Komentáře