こんにちは。株式会社リンクネット、ソリューション事業部の高橋です。
最近弊社ではPHPのバージョンアップに関する需要が増えています。
PHPのバージョンアップの際には、関数が削除されたり、
引数の数が変わるなどソースコードを修正する必要が生じます。
これらの変更を目視で確認し修正するのは大変なため、
何かツールがないか探してみたところ、PHPの静的解析ツールであるPHPStan
が有効そうでした。
本記事では PHPStan
がPHPのバージョンアップに適しているか検証します。
$ php -v
PHP 8.1.24 (cli) (built: Oct 6 2023 09:46:19) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.24, Copyright (c) Zend Technologies
with Zend OPcache v8.1.24, Copyright (c), by Zend Technologies
今回は解析対象のソースコードのドキュメントルートに composer
を使用して、 PHPStan
をインストールします。
$ composer require --dev phpstan/phpstan
今回は素のPHPを対象としていますが、Laravel
で静的解析をする場合は、
下記のようにcomposer
を使用して、 larastan
をインストールします。
$ composer require --dev -W phpstan/phpstan phpstan/extension-installer nunomaduro/larastan
PHPStan
の設定はコマンド時に指定可能ですが、
何度も実行することを想定して、設定ファイルを作成します。
$ vi phpstan.dist.neon
phpstan.dist.neonの中身は下記です。
levelは解析時のレベル、pathsは解析対象のディレクトリを指定します。
parameters:
level: 1
paths:
- src
各levelの詳細は下記を参照
https://phpstan.org/user-guide/rule-levels
設定ファイルを指定して実行する場合は下記のコマンドで実行します。
$ ./vendor/bin/phpstan analyze -c ./phpstan.dist.neon
一度、実行してしまえば、以降は下記のような短縮されたコマンドで実行できます。
$ ./vendor/bin/phpstan analyze
現在は廃止されたcreate_function
を対象に静的解析を実行します。
ソースコードは下記です。
<?php
// php8.0で廃止されて記述方法
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo $newfunc(2, M_E) . "\n";
// php8.0でも使える記述方法
$newfunc = function($a,$b) { return "ln($a) + ln($b) = " . log($a * $b); };
echo $newfunc(2, M_E) . "\n";
実行結果は下記です。
想定通り、PHPの実行結果、PHPStanの実行結果はともにcreate_function
が存在しないのでエラーになっています。
$ php ./src/test70.php
PHP Fatal error: Uncaught Error: Call to undefined function create_function() in /home/appuser/project/phpstan/src/test70.php:2
Stack trace:
#0 {main}
thrown in /home/appuser/project/phpstan/src/test70.php on line 2
[ERROR] Found 1 error
$ ./vendor/bin/phpstan analyze
Note: Using configuration file /home/appuser/project/phpstan/phpstan.dist.neon.
------ ---------------------------------------------------------------------
Line test70.php
------ ---------------------------------------------------------------------
3 Function create_function not found.
💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
------ ---------------------------------------------------------------------
[ERROR] Found 1 error
php8.0以降mixed
やmatch
といった単語は予約語になりました。
よって、クラスやインターフェース、 トレイトの名前として使えなくなっています。
そのため、関数と同様に下記のようなmixed
をクラス名とした際は、
PHPの実行時と静的解析でともにエラーになると推測できます。
<?php
class mixed{
public string $str;
function __construct()
{
$this->str = "";
}
public function index():bool
{
echo $this->str.PHP_EOL;
return true;
}
}
$old = new mixed();
$old->str = 'hoge';
$old->index();
class mixedClass{
public string $str;
function __construct()
{
$this->str ='';
}
public function index():bool
{
echo $this->str.PHP_EOL;
return true;
}
}
$new = new mixedClass();
$new->str = 'hoge';
$new->index();
PHPの実行結果は下記です。 想定通りエラーが発生しています。
$ php ./src/test70.php
PHP Fatal error: Cannot use 'mixed' as class name as it is reserved in /home/appuser/project/phpstan/src/test70.php on line 3
静的解析の実行結果は下記です。
想定と異なりエラーとなりませんでした。
予約語のチェックには使用できないようです。
$./vendor/bin/phpstan analyze
Note: Using configuration file /home/appuser/project/phpstan/phpstan.dist.neon.
[OK] No errors
PHPStan
を用いて、PHPのバージョンアップ対応に利用できないか、
試してみましたが関数については問題なくチェックできるようですが、
予約語には対応できていませんでした。
ただし、予約語はIDE(統合開発環境)ではエラーとなっていたたため、
Xdebug
などと組み合わせれば十分役に立つと考えられます。
また解析レベルを上げることで、静的な型付けを正しくチェックできるため、 規模の大きい案件ではあったほうが潜在的なバグが見つけやすく有用なツールであると考えられます。