WordPressのプラグインリポジトリはSVNで運用されているが、pre-commitフックという機能を使い、「コミット前にPHPの構文エラーをチェックする」ことが行われるようになった。この構文チェックはPHP7で行われている。
So, make sure to check your code with PHP 7. It’s no fun for people using the newest systems, like we always recommend, to be running into syntax errors. Note that these were actually syntax errors in previous versions of PHP as well (using break and continue makes no sense outside of a loop structure), but now you’re getting told about them by the lint process.
Known issues with pre-commit to the plugins SVN
ではこの構文チェックがなにで行われているかと言うと、PHP標準のリンターのようだ。php -l file.php
で行う。このチェックでは構文チェックが走るだけである。
pre-commitエラーの仕組み
さて、筆者はGianismというプラグインをTravis経由で自動デプロイしているのだが、その過程でこのpre-commitフックのエラーチェックを通らないことに気づいた。次のようなエラーメッセージが表示されるのである。
vendor/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php
Fatal error: Cannot declare class ArithmeticError, because the name is already in use in Standard input code on line 5
要は「ArithmeticError.phpはすでに定義されているから定義してはダメです、やりなおし」ということなのだが、なぜこんなことが起きるようになったのか、筆者はそれなりの時間を使って解決するハメになったのでその原理と解決方法を紹介したい。
まず、このエラーが再現する条件は次の通り。
- symfony/polyfillを使っている。ただし、composerなどで依存関係が解決される場合、勝手に入ることがある。筆者の場合は google/api-client → Guzzle → symfony/polyfill という感じで勝手に入っていた。Guzzleはいろんなプロジェクトが利用するので、要注意だ。
- ビルドをPHP5.6で行っている。WordPressの現在の必須要件が5.6なので、普通そうだと思うが。
上記の条件を満たしていると、composerはまず「ライブラリでPHP5.6でも動くようにpolyfillを入れよう」と判断する。ただし、composerは遅延ローディングという機能を持っているので、「該当するクラスがなければ必要な時にファイルを読み込む」というお利口な処理を行ってくれる。ArithmeticError
の場合でいうと、PHP7以上なら標準クラスとして存在するので何もしない、5.6ならArithmeticError.php
を読み込むという具合だ。
さて、WordPressのプラグインリポジトリでは、コミットされたすべてのPHPファイルに対して構文エラーをチェックする。構文をチェックするためにはファイルを読み込まないといけないが、ファイルをパースした段階でクラス再定義の致命的エラーが発生するようである。
pre-commitエラーの解決策
この問題は筆者と同じように自動デプロイなどをしている人が気づいたようで、symfony/polyfillに対してプルリクエストが送られている。だが、このプルリクエストは「WordPressで直してね」とクローズされてしまったので、polyfill側からすると「知らんがな」ということなのだろう。
if wordpress has issues how to properly deal with code, it shall be fixed on wordpress level, if you ask me
@keradus
WordPress側の構文エラーチェックの仕組みがおかしいという私的には妥当性があり、すでに遅延ローディングを前提としているsymfony/polyfillにPHPのバージョンチェックを入れることは難しいだろう。該当するプルリクエストでもWordPressコミュニティで見たことのある人がコメントを書いているが、やや説得力に欠く。とはいえ、WordPress側の構文チェックがすぐに改善されることはないだろう。
したがって、いまのところ解決策は次のパッチを当てることである。
# ディレクトリまで移動
cd /path/to/your/wordpress_plugin/trunk
# パッチをダウンロード
curl https://gist.github.com/bshaffer/904b596beecdfbb0a39cb3cd07728720/raw > polyfill-php70.diff
# パッチを適用
patch -p1 < polyfill-php70.diff
実際に動くコードとしては、Gianismのビルドスクリプトを参考にして欲しい。
というわけで、今回はちょっとしたティップスを紹介した。リリースできなくて困っていた人の参考になれば幸いである。