Software engineering from east direction

六本木一丁目で働くソフトウェアエンジニアのブログ

PHPコードでの、`empty()`避けようねとか`===`のほうがベター、などは phpstan/phpstan-strict-rules を使って指摘しよう

TL;DR

  • PHPアプリケーションにおいて、表題のような「PHPを使う上で自制心を持とうな」みたいな温度感でstrictな書き方を推奨される昨今
  • こういうのは往々にして人間が言うのはそのうちげんなりしてくるし、逆に言われる方も同じ
  • PHPStanが提供しているカスタムルール phpstan/phpstan-strict-rules を使おう

前提

PHPStanを使うことを前提としています。

phpstan/phpstan-strict-rules

github.com

PHPStanは、「PHPStanでCustomRuleを作る」という発表でも解説されている通り、任意のカスタムルールをクラスとして定義することで、ルールを追加できます。しかし、すでにPHPStanが提供しているルールもいくつかあります。その一つが phpstan/phpstan-strict-rules です。

導入方法は

かんたんで、 composer require --dev phpstan/phpstan-strict-rules でinstallしてから、 PHPStanの設定ファイル(ex. phpstan.neon)に加える。

すべてのチェック項目を加えたい場合はincludesに追加すれば良い。

parameters:
  level: max
  paths:
    - src
    - tests
  ignoreErrors:
    - '#Dynamic call to static method PHPUnit\\Framework\\.*#'
includes:
  - vendor/phpstan/phpstan-phpunit/extension.neon
  - vendor/phpstan/phpstan-strict-rules/rules.neon

個別の項目を一つずつ加えたい場合は、servicesに追加すれば良い。

services:
  -
    class: PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule
    tags:
      - phpstan.rules.rule
  -
    class: PHPStan\Rules\StrictCalls\StrictFunctionCallsRule
    tags:
      - phpstan.rules.rule

どういう指摘をしてくれるか

たとえば、 empty() を使用したコードが有る場合は次のように指摘される

Construct empty() is not allowed. Use more strict comparison

あるいは、in_array() の第三引数をtrueにしていない場合はこう

Call to function in_array() requires parameter #3 to be set.

その他指摘される項目は、GitHubのREADME.mdにずらっと書いてあるので、自分たちにとって全て取り入れられるのか・一部のみなのかを判断するとよい。

導入の注意点

すべてのルールを適用すると、phpstan/phpstan-phpunitを入れていても、PHPUnitを用いたテストコードが次のように怒られてしまいます。

/Users/kazukihigashiguchi/src/github.com/hgsgtk/example/tests/Api/ClientTest.php:54:Dynamic call to static method PHPUnit\Framework\Assert::assertSame().
/Users/kazukihigashiguchi/src/github.com/hgsgtk/example/tests/Api/ClientTest.php:155:Dynamic call to static method PHPUnit\Framework\Assert::assertSame().
/Users/kazukihigashiguchi/src/github.com/hgsgtk/example/tests/Api/ClientTest.php:191:Dynamic call to static method PHPUnit\Framework\Assert::fail().
/Users/kazukihigashiguchi/src/github.com/hgsgtk/example/tests/Api/ClientTest.php:233:Dynamic call to static method PHPUnit\Framework\Assert::assertSame().

こういうのは、Issueにもある通り、ignore patternに追加することで対応しましょう。

  ignoreErrors:
    - '#Dynamic call to static method PHPUnit\\Framework\\.*#'