QAツール(PHP)
composer-require-checker
composer-require-checkerは、利用しているライブラリ・php拡張を
composer.json(require)で全て記載できているかのチェッカーです。(開発環境のみで利用するライブラリ除く)
メリット
- 開発環境で利用している(dev)ライブラリを本番稼働するコードで利用しエラーになることを防ぐ
- composer.jsonを見れば書いたコードで使っているライブラリ・フレームワークがひと目で分かる
補足
- 最新版(4.0.0)は>=PHP8.0.2
- composer-require-checker.pharをダウンロードして利用(Laravelのルートに設置)
- 私の環境がPHP7.4だったため、v3.8.0を利用
https://github.com/maglnet/ComposerRequireChecker
実行結果
# php composer-require-checker.phar check composer.json
ComposerRequireChecker 3.8.0@537138b833ab0f9ad72b667a72bece2a765e88ab
The following 10 unknown symbols were found:
+--------------------------------------+--------------------+
| Unknown Symbol | Guessed Dependency |
+--------------------------------------+--------------------+
| DB | |
| GraphQL\Type\Definition\ResolveInfo | |
| gzdecode | ext-zlib |
| json_decode | ext-json |
| json_encode | ext-json |
| JSON_UNESCAPED_UNICODE | ext-json |
| mb_strlen | ext-mbstring |
| mb_strpos | ext-mbstring |
| simplexml_load_file | ext-SimpleXML |
| Symfony\Component\DomCrawler\Crawler | |
+--------------------------------------+--------------------+
対応
- 1.ext-xxx
- デフォルトでext-xxxは組み込みされているがcomposer.jsonに記載されていないためエラーになる
- 「composer require ext-json」でcomposer.json更新
- https://engineering.otobank.co.jp/?page=1600933810
- 2.composer.jsonで記載されているライブラリ・フレームワークの依存パッケージを利用
- 例)Symfony\Component\DomCrawler\Crawler
- composer require symfony/dom-crawlerで更新
- 例)Symfony\Component\DomCrawler\Crawler
- 3.Laravelの場合クラスエイリアスを利用すると、composer.jsonに記載されていてもエラーになる為クラスエイリアスを利用しない形に修正する
問題
クラスエイリアスのDB(Illuminate\Support\Facades\DB)を使っている影響なのか
「illuminate/support」をcomposer requireしても変わらなかった。
DBの部分を\Illuminate\Support\Facades\DBに書き換えることでエラーはでなくなる。
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires illuminate/database ^8.76, found illuminate/database[v8.76.0, v8.76.1, v8.76.2, 8.x-dev] but these were not loaded, likely because it conflicts with another require.
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
修正
$sql = DB::table('books')
↓
$sql = \Illuminate\Support\Facades\DB::table('books')
実行結果:(正常終了)
# php composer-require-checker.phar check composer.json
ComposerRequireChecker 3.8.0@537138b833ab0f9ad72b667a72bece2a765e88ab
There were no unknown symbols found.
larastan
Laravel用のphpstanです。
インストール
composer require nunomaduro/larastan --dev
検査コマンド:
./vendor/bin/phpstan analyse
設定ファイル
includes:
- ./vendor/nunomaduro/larastan/extension.neon
parameters:
paths:
- app
- bootstrap
- config
- database
- routes
- packages
level: 0
実行結果(Level0)
# ./vendor/bin/phpstan analyse
Note: Using configuration file /usr/share/nginx/html/phpstan.neon.
110/110 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
------ -----------------------------------------------------------------------
Line packages/Domain/Base/ValueObject/Enum.php
------ -----------------------------------------------------------------------
29 Instantiated class Packages\Domain\Base\ValueObject\Enum is abstract.
------ -----------------------------------------------------------------------
------ ---------------------------
Line routes/console.php
------ ---------------------------
18 Undefined variable: $this
------ ---------------------------
-- -----------------------------------------------------------------------------------------------------
Error
-- -----------------------------------------------------------------------------------------------------
Child process error (exit code 255):
Symfony\Component\ErrorHandler\Error\FatalError
Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)
at phar://vendor/phpstan/phpstan/phpstan.phar/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php:63
59▕ $count = \count($this->types);
60▕ foreach ($tokens as &$match) {
61▕ for ($i = 1; $i <= $count; $i++) {
62▕ if ($match[$i] !== null && $match[$i] !== '') {
➜ 63▕ $match = [$match[0], $this->types[$i - 1]];
64▕ break;
65▕ }
66▕ }
67▕ }
Whoops\Exception\ErrorException
Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)
at phar://vendor/phpstan/phpstan/phpstan.phar/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php:63
59▕ $count = \count($this->types);
60▕ foreach ($tokens as &$match) {
61▕ for ($i = 1; $i <= $count; $i++) {
62▕ if ($match[$i] !== null && $match[$i] !== '') {
➜ 63▕ $match = [$match[0], $this->types[$i - 1]];
64▕ break;
65▕ }
66▕ }
67▕ }
+1 vendor frames
2 [internal]:0
Whoops\Run::handleShutdown()
Child process error (exit code 255):
-- -----------------------------------------------------------------------------------------------------
[ERROR] Found 4 errors
Instantiated class Packages\Domain\Base\ValueObject\Enum is abstract.
Packages\Domain\Base\ValueObject\Enumが抽象クラス(abstract)なのですが
それをインスタンス化(new)した為に起きた警告と思われます。
(get_called_classで継承したクラス名を取得して、それをインスタンス化しているはずなので
Enum自体がインスタンス化されることはない気がしますが、larastanでの検査ではそのように認識されてしまうのか?よく分からなかったです)
final public static function __callStatic($label, $args)
{
$class = get_called_class();
$const = constant("$class::$label");
return new $class($const);
}
こちらはenumを自前で用意していたので「laravel-enum」に置き換え
Class Packages\Domain\Novel\ValueObject\APIParametor\UserId does not have a constructor and must be instantiated without any parameters.
__constructのtypoが原因だった...。これまでなぜエラーにならなかったのか謎。
Access to an undefined property Packages\Domain\Novel\Entity\NovelAPIParametorEntity::$user_id.
クラスのプロパティにアクセスできないために警告がでています。
これはこのプロパティが存在しなかった為、プロパティを追加しました。
routes/console.phpでのUndefined variable: $this
------ ---------------------------
Line routes/console.php
------ ---------------------------
18 Undefined variable: $this
------ ---------------------------
クロージャ内での$thisの誤検知は現状対応する術がないぽい。
excludePathsでチェックから外すようにしました。
Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)
メモリエラーになる場合は「memory-limit」オプションを指定する
./vendor/bin/phpstan analyse --memory-limit=1G
実行結果(Level1)
Variable $urlList might not be defined.
変数が定義(初期化)されていない為に警告がでていた。
実行結果(Level2)
Result of method Packages\Infrastructure\Repositories\ScopperSokuhouRecommendScrapingRepository::execute()
(void) is used.
返り値がなにもないがreturn している為エラーになっている。retrunを外して対応