PHP の移行後のコードの品質
PHP 8 系で動くようになっても、古い書き方のままでは、不具合の起きやすさは変わりません。PHP 8 系では、型で誤りを防ぎ、ツールで実行の前に不具合を見つける仕組みが整っています。
型の追加、静的解析、テスト、書き方の統一を、CI で変更のたびに動かす仕組みまで、KEY SELECT がお引き受けできます。
すべての作業を、セキュリティを意識して進めます。
品質を高める仕組み
動かして
型
引数、戻り値、プロパティに型を書くと、違う値が渡ったときに止まり、ツールが誤りを指摘できます。enum や readonly のクラスで、取り得る値と変更の範囲も限れます。
静的解析
PHPStan が、コードを実行せずに、存在しないメソッドの呼び出しや型の食い違いを見つけます。厳しさを 0 から 10 のレベルで上げていけます。
テスト
PHPUnit や
非推奨の検出
次の
書き方の統一
PER Coding Style に
依存パッケージの検査
Composer のパッケージの既知の脆弱性を、composer audit で検査します。Composer 2.9 からは、脆弱性のあるバージョンを既定で入れません。
お引き受けできること
大きなシステムでも、今の状態を記録してから、新しいコードと直したコードから少しずつ品質を上げられます。開発と保守を一体で行うため、品質を高めながら機能の追加も進められます。
今の状態の診断
静的解析と
型の追加
Rector で
PHPStan の導入とレベルの引き上げ
今ある
テストの整備
テストの
CI の整備
テスト、
セキュリティの検査
SCA、
進め方
一度に
今の
状態の 記録 静的解析の
今の 指摘を ベースラインに 記録し、 テストの 範囲を 確かめます。 新しい
問題を 止める CI で
検査を 動かし、 新しい コードと 直した コードには、 必ず型と テストを 付けます。 少し
ずつ直す ベースラインの
指摘を、 影響の 大きい 箇所から 減らしていきます。 レベルを
上げる 指摘が
減ったら、 静的解析の レベルと Rector の ルールを 1 段ずつ 上げます。 保守で
続ける 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 | スカラーの |
| PHP 7.1 | null を?string)、void、iterable |
| PHP 7.2 | object |
| PHP 7.4 | プロパティの |
| PHP 8.0 | 複数のint|string)、mixed、static |
| PHP 8.1 | enum、never、A&B) |
| PHP 8.2 | readonly の(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
ご相談・ お問い合わせ
内容が