PHP の移行後のコードの品質

PHP 8 系で動くようになっても、古い書き方のままでは、不具合の起きやすさは変わりません。PHP 8 系では、型で誤りを防ぎ、ツールで実行の前に不具合を見つける仕組みが整っています。
型の追加、静的解析、テスト、書き方の統一を、CI で変更のたびに動かす仕組みまで、KEY SELECT がお引き受けできます。
すべての作業を、セキュリティを意識して進めます。

品質を高める仕組み

動かしてはじめて分かる不具合を、本番に出る前に見つけるための仕組みです。どれも、PHP 8 系に上げたあとに効果が大きくなります。

型

引数、戻り値、プロパティに型を書くと、違う値が渡ったときに止まり、ツールが誤りを指摘できます。enum や readonly のクラスで、取り得る値と変更の範囲も限れます。

静的解析

PHPStan が、コードを実行せずに、存在しないメソッドの呼び出しや型の食い違いを見つけます。厳しさを 0 から 10 のレベルで上げていけます。

テスト

PHPUnit や Pest の自動テストと、ブラウザでの操作のテストで、変更のたびに動きが変わらないことを確かめます。

非推奨の検出

次のバージョンで動かなくなる書き方の警告は、本番の設定では表示されません。テストで見つけて、警告のうちに直します。

書き方の統一

PER Coding Style に合わせて、PHP-CS-Fixer で自動で整えます。レビューを、書き方ではなく中身に集中できます。

依存パッケージの検査

Composer のパッケージの既知の脆弱性を、composer audit で検査します。Composer 2.9 からは、脆弱性のあるバージョンを既定で入れません。

お引き受けできること

大きなシステムでも、今の状態を記録してから、新しいコードと直したコードから少しずつ品質を上げられます。開発と保守を一体で行うため、品質を高めながら機能の追加も進められます。

今の状態の診断

静的解析とテストの状況を調べ、不具合の起きやすい箇所と、品質を上げる順番をご報告します。

型の追加

Rector で確実に分かる型を足し、配列の中身などは PHPDoc で補います (Rector での書き換え)。

PHPStan の導入とレベルの引き上げ

今ある指摘はベースラインに記録し、新しく増える指摘だけを止めながら、レベルを少しずつ上げます。

テストの整備

テストのないシステムでも、主な処理と画面の操作から、自動テストを足していけます。

CI の整備

テスト、静的解析、書き方の検査、依存パッケージの検査を、GitHub Actions などで変更のたびに動かします。

セキュリティの検査

SCA、SAST、DAST で、パッケージ、コード、動いているアプリケーションを検査し、報告書にまとめられます。

進め方

一度にすべてを直すのではなく、新しく増える問題を止めてから、既存のコードを少しずつ直します。

  1. 今の状態の記録

    静的解析の今の指摘をベースラインに記録し、テストの範囲を確かめます。

  2. 新しい問題を止める

    CI で検査を動かし、新しいコードと直したコードには、必ず型とテストを付けます。

  3. 少しずつ直す

    ベースラインの指摘を、影響の大きい箇所から減らしていきます。

  4. レベルを上げる

    指摘が減ったら、静的解析のレベルと Rector のルールを 1 段ずつ上げます。

  5. 保守で続ける

    PHP とツールの新しいバージョンに合わせて、検査を更新し続けます (移行後の保守)。

技術者の方へ

型の書き方と、ツールの設定の例です。ツールのバージョンと設定の名前は、2026 年 10 月 25 日時点の各ツールの公式のドキュメントによります。

型を付ける前と後

<?php
// 移行の直後: 型がなく、配列の中身も分からない
function subtotal($items)
{
    $sum = 0;
    foreach ($items as $item) {
        $sum += $item['price'] * $item['qty'];
    }
    return $sum;
}
<?php
declare(strict_types=1);

// 税率を enum で表し、取り得る値を限る(8.1 から)
enum TaxRate: string
{
    case Standard = 'standard';
    case Reduced = 'reduced';

    public function rate(): float
    {
        return match ($this) {
            self::Standard => 0.10,
            self::Reduced => 0.08,
        };
    }
}

// 明細を、変更できないクラスで表す(readonly クラスは 8.2 から)
final readonly class LineItem
{
    public function __construct(
        public int $price,
        public int $quantity,
        public TaxRate $taxRate,
    ) {}
}

/** @param list<LineItem> $items */
function subtotal(array $items): int
{
    $sum = 0;
    foreach ($items as $item) {
        $sum += $item->price * $item->quantity;
    }
    return $sum;
}

strict_types

  • ファイルの最初に declare(strict_types=1); を書くと、そのファイルからの関数の呼び出しで、型の自動の変換が止まり、合わないと TypeError になります
  • 戻り値は、関数を定義したファイルの決まりで検査されます。対象は int、float、string、bool のスカラーの型だけで、int は float の型を通ります

バージョンごとに使えるようになった型

バージョン使えるようになった型
PHP 7.0スカラーの型の宣言 (int、float、string、bool)、戻り値の型
PHP 7.1null を許す型 (?string)、void、iterable
PHP 7.2object
PHP 7.4プロパティの型
PHP 8.0複数の型のどれか (int|string)、mixed、戻り値の static
PHP 8.1enum、readonly のプロパティ、戻り値の never、複数の型をすべて満たす型 (A&B)
PHP 8.2readonly のクラス、(A&B)|null のような組み合わせ、null・false・true の単独の型
PHP 8.3クラスの定数の型
PHP 8.4プロパティフック、読み書きで公開の範囲を分ける書き方 (public private(set))、#[\Deprecated]

PHPStan の設定 (phpstan.neon)

# 今ある指摘は phpstan-baseline.neon に記録する(--generate-baseline)
includes:
    - phpstan-baseline.neon
parameters:
    level: 6
    paths:
        - src
        - tests

PHPStan 2.3 のレベルは 0 から 10 です。レベル 10 (PHPStan 2.0 から) は、型が書かれていない値も報告します。phpstan-strict-rules で == や empty() の禁止などを、phpstan-deprecation-rules で @deprecated の使用の検出を足せます。

非推奨をテストで失敗にする (phpunit.xml)

<phpunit displayDetailsOnTestsThatTriggerDeprecations="true"
         failOnDeprecation="true">
    <source>
        <include>
            <directory>src</directory>
        </include>
    </source>
</phpunit>

PHPUnit 13 は PHP 8.4 以上、12 は PHP 8.3 以上が必要です。<source> で自分のコードを指定すると、依存パッケージが出した非推奨と分けて扱えます。

CI の例 (GitHub Actions)

strategy:
  matrix:
    php: ['8.4', '8.5']
steps:
  - uses: shivammathur/setup-php@v2
    with:
      php-version: ${{ matrix.php }}
  - run: composer install
  - run: composer audit
  - run: vendor/bin/php-cs-fixer fix --dry-run --diff
  - run: vendor/bin/phpstan analyse
  - run: vendor/bin/rector --dry-run
  - run: vendor/bin/phpunit

ご相談・お問い合わせ

内容が固まっていない段階からご相談いただけます。各分野のプロフェッショナルがご対応いたします。ご相談・お見積もりは無料です。