PHP5で動く、PHP7なんか動きが違う、原因は?何をチェックすべき?

PHP5で動く、PHP7なんか動きが違う、原因は?何をチェックすべき?のイメージ php

PHP5とPHP7の違いは、ワードプレスを使っている限りほとんど意識することはありません。レンタルサーバーのコントロールパネルからPHPのバージョンを5.6.x系から7.0、7.1、7.2系に切り替えるだけでそのまま動きます。互換性の問題は発生しないのが素晴らしいです。よく考えられたアップデートだと思っていたんですが、5.6.x系・7.0系=>7.1系のアップデートは、とても気づきにくい罠がありました。知っていましたか?負の offset をサポートするようになりました。って一文でfile_get_contentsが別物の動きをしていました。

PHP5.6では、思い通り、設計通りの動作をしていたプログラムがありました。
このプログラムは、macOSで動かしていて、先日macOSをSierraからHigh Sierraにアップグレードしました。
macOS Sierraは、PHP5.6系です。macOS High Sierraは、PHP7.1系がすぐに使える状態で入っています。
この違いは、プログラムの結果が求めている動作をしていないことで初めて知りました。

PHPのマイグレーションをページに新機能、新しい関数、下位互換性のない変更点、推奨されなくなる機能、変更された関数、その他の変更など、PHPのバージョンをあげる前に注意するべきポイントがまとまっているので参考にしています。
メニューから各バージョンのマイグレーションを選択することができます。
参考:PHP7.0.xからPHP7.1.xへの移行

今回、発生した問題は、この移行ページに掲載されていました。
PHP 7.0.x から PHP 7.1.x への移行>変更された関数 >ファイルシステム

file_get_contents() now accepts a negative seek offset if the stream is seekable.

さらりと1行でまとまっています。

file_get_contents関数はファイルを読み込んだり、URLからWEBページを取得できるよく使われる関数の一つです。
PHP5のfile_get_contents関数の説明はこんな感じでした。
PHP5が最新だった頃のfile_get_contentsの解説(php.net)
それが、PHP7.1の変更後、このように変わっていました。
php7.2.2が最新の頃のfile_get_contentsの解説(php.net)

違いわかるでしょうか?そうです!$offsetのデフォルト値が-1から0に変わっています。マニュアル上はこのように変わっていますが、PHP5.6はいままで通り-1を渡しても0と同じ意味です。

一方、$offsetに-1を渡すようなプログラムをPHP7.1以降で動かすと、 ストリームの末尾からのオフセットと解釈されます。

=>PHP5で動く、PHP7.1で動きがおかしい原因はこれでした。

関数のデフォルト値って不変、ずっと変わらないものって思い込んでいました。現実は、バージョンアップで変わることがあるってことです。ファイル名以外、引数を指定することがないって方も多いかと思います。

作り込んだライブラリで、拡張性を持たせるためにPHPのデフォルト引数も全て受け付けるようなラッパー関数、ヘルパー関数はPHPのデフォルト値を自作関数、メソッドの引数にコーディングすることが多いです。

PHP5で動いていたものがPHP7で動かなくなったら、チェックすべきポイント

PHPのマイグレーションには、たった1行の変更点の記載でしたが、インパクトが大きいってことがわかったかと思います。
自作関数、自作メソッドでPHPのデフォルトを書いているところは、マニュアルを参考にし、再確認するのが良いかと思います。

この際、マイグレーションページを見ながら、記載のある関数を使っているかgrepやIDEの検索機能をフルに使ってチェックするのが効率的です。

=>マイグレーションページをインデックスにし、関数のマニュアルとソースを比較!

まとめ

繰り返しになりますが、PHP5とPHP7の違いは、ワードプレスを使っている限りほとんど意識することはありません。今回のfile_get_contentsに関しても完全互換性があり、ファイル名のみの指定で使っていると同一です。でもデフォルト引数の違いがありましたね。拡張性を考えたメソッドやヘルパ関数は標準と同じような引数を許可するような設計はこういった変更のインパクトが大きいって思いましたよ。

0と-1で別物の動きになってしまいますから・・

コメント

タイトルとURLをコピーしました