Laravel PHP Insightsを使ってコード品質を分析する

<img width="617" alt="スクリーンショット 2019-05-17 13.03.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/5b4a99bd-b73b-7b85-ac70-b5803c820538.png">

## PHP Insights

[公式 - phpinsights](https://phpinsights.com)
[GitHub - nunomaduro/phpinsights](https://github.com/nunomaduro/phpinsights)

- コード品質とコーディングスタイルを分析するPHPの品質チェックツール
- コードの信頼性、疎結合、シンプルさ、セキュリティを高めます
- PHPCS, PHPLOC, EasyCodingStandard をラッパーしたコンソールインターフェース
- Laravel, Symfonyフレームワークにお手軽に導入可
  - 素のPHPでも使用可能

## インストール要件

- PHP 7.2 以降

## インストール

```shell-session
$ composer require nunomaduro/phpinsights --dev
```

## 設定ファイルのコピー

```shell-session
$ php artisan vendor:publish --provider="NunoMaduro\PhpInsights\Application\Adapters\Laravel\InsightsServiceProvider"
```

[./vendor/nunomaduro/phpinsights/stubs/laravel.php](https://github.com/nunomaduro/phpinsights/blob/master/stubs/laravel.php) のファイルが `./config/insights.php` にコピーされます。

設定例

```php:config/insights.php
<?php declare(strict_types=1);

use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenDefineFunctions;
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenFinalClasses;
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenNormalClasses;
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenPrivateMethods;
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenTraits;
use NunoMaduro\PhpInsights\Domain\Metrics\Architecture\Classes;
use PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\UnnecessaryFinalModifierSniff;
use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff;
use SlevomatCodingStandard\Sniffs\Commenting\UselessFunctionDocCommentSniff;
use SlevomatCodingStandard\Sniffs\ControlStructures\DisallowShortTernaryOperatorSniff;
use SlevomatCodingStandard\Sniffs\ControlStructures\DisallowEmptySniff;
use SlevomatCodingStandard\Sniffs\Namespaces\AlphabeticallySortedUsesSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\DeclareStrictTypesSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\DisallowMixedTypeHintSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\ParameterTypeHintSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\PropertyTypeHintSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSniff;

return [

    /*
    |--------------------------------------------------------------------------
    | Default Preset
    |--------------------------------------------------------------------------
    |
    | This option controls the default preset that will be used by PHP Insights
    | to make your code reliable, simple, and clean. However, you can always
    | adjust the `Metrics` and `Insights` below in this configuration file.
    |
    | Supported: "default", "laravel", "symfony", "magento2", "drupal"
    |
    */

    'preset' => 'laravel',

    /*
    |--------------------------------------------------------------------------
    | IDE
    |--------------------------------------------------------------------------
    |
    | This options allow to add hyperlinks in your terminal to quickly open
    | files in your favorite IDE while browsing your PhpInsights report.
    |
    | Supported: "textmate", "macvim", "emacs", "sublime", "phpstorm",
    | "atom", "vscode".
    |
    | If you have another IDE that is not in this list but which provide an
    | url-handler, you could fill this config with a pattern like this:
    |
    | myide://open?url=file://%f&line=%l
    |
    */

    'ide' => null,

    /*
    |--------------------------------------------------------------------------
    | Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may adjust all the various `Insights` that will be used by PHP
    | Insights. You can either add, remove or configure `Insights`. Keep in
    | mind that all added `Insights` must belong to a specific `Metric`.
    |
    */

    'exclude' => [
        //  'path/to/directory-or-file'
    ],

    'add' => [
        Classes::class => [
            ForbiddenNormalClasses::class,
        ],
    ],

    'remove' => [
        AlphabeticallySortedUsesSniff::class,
        DeclareStrictTypesSniff::class,
        DisallowMixedTypeHintSniff::class,
        DisallowShortTernaryOperatorSniff::class,
        ForbiddenDefineFunctions::class,
        ForbiddenFinalClasses::class,
        ForbiddenTraits::class,
        ParameterTypeHintSniff::class,
        PropertyTypeHintSniff::class,
        ReturnTypeHintSniff::class,
        UselessFunctionDocCommentSniff::class,
        UnnecessaryFinalModifierSniff::class
    ],

    'config' => [
        ForbiddenPrivateMethods::class => [
            'title' => 'The usage of private methods is not idiomatic in Laravel.',
        ],
        LineLengthSniff::class => [
            'lineLimit' => 120,
            'absoluteLineLimit' => 160,
            'exclude' => [
                'app/Models',
                'lang',
            ],
        ],
        DisallowEmptySniff::class => [
            'exclude' => [
                'app/Http/Middleware/RedirectIfAuthenticated.php',
            ],
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Requirements
    |--------------------------------------------------------------------------
    |
    | Here you may define a level you want to reach per `Insights` category.
    | When a score is lower than the minimum level defined, then an error
    | code will be returned. This is optional and individually defined.
    |
    */

    'requirements' => [
//        'min-quality' => 0,
//        'min-complexity' => 0,
//        'min-architecture' => 0,
//        'min-style' => 0,
//        'disable-security-check' => false,
    ],

    /*
    |--------------------------------------------------------------------------
    | Threads
    |--------------------------------------------------------------------------
    |
    | Here you may adjust how many threads (core) PHPInsights can use to perform
    | the analyse. This is optional, don't provide it and the tool will guess
    | the max core number available. This accept null value or integer > 0.
    |
    */

    'threads' => null,

];
```

## 使い方

```shell-session
$ php artisan insights
```

### コマンドオプション - 詳細表示

```shell-session
$ php artisan insights -v
```

デフォルトだと、最初の3つの問題のみ表示されますが `-v` オプションを付けるとすべて表示されます。

### 評価の項目

- Code コード評価
- Complexity 複雑さ評価
- Architecture アーキテクチャ評価
- Style コーディングスタイルやセキュリティ等の評価

上記の4項目から評価されます。

### 評価のスコア

評価のスコアは 1 〜 100 点です。

- 赤: 1-49
- 黄: 50-79
- 緑: 80-100

がんばって緑を目指しましょう😎

## 自動修正

修正可能な項目をコマンド実行して適用します。

```shell-session
$ php artisan insights --fix
```

v2系から追加されました。
https://github.com/nunomaduro/phpinsights/pull/337/files

## GitHub Actions

```yml:.github/workflows/insights.yml
name: Insights

on:
  - pull_request

jobs:
  phpinsights:
    runs-on: ubuntu-latest

    name: PHP Insights checks
    steps:
      - uses: actions/checkout@v3

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.1

      - name: Install Dependencies
        run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --prefer-dist

      - name: Insights Analyse
        run: php artisan insights -n --ansi --format=github-action
```

## まとめ

コーディングスタイルのチェックはもちろんのこと、
未使用の変数や無駄な括弧、Todoコメントなど様々細かく指摘してもらえます。
使用しているライブラリにセキュリティ問題があった場合も検知します。

導入は簡単なのでもしよかったらお試しください😊

## 参考

- [PHP Insights - Laravel News](https://laravel-news.com/php-insights)
- [GitHub - nunomaduro/phpinsights: 💡Instant PHP quality checks from your console](https://github.com/nunomaduro/phpinsights)