php4からphp5へ


PHPバージョン7.0がリリースされたのが2015年12月。

もう1年と数か月が経過しようとしている昨今においては、ニーズがないと思いますが、PHP4からPHP5へ移行する際の留意点について簡単にメモを残しておきたいと思います。

PHP4.4.4で構築されたWEBシステムをPHP5.3.3へ実際に移行した時の留意事項です。

PHP5.6のサポート切れが2017年8月28日に予定されているご時世の中、”何故5.3.3?”という疑問は当然ですが、大人の事情でそうなりました(笑)。

では、いくつかパターン別に要対応箇所と対応案を列挙します。

1.非推奨となった関数への対応

PHP5.3.0で非推奨となり、PHP7.0.0で削除される関数に以下のようなものがあります。

非推奨となる関数 代替えとして使用可能とされている関数
ereg() preg_match()
ereg_replace() preg_replace()
eregi() preg_match() (i 修飾子を使う)
eregi_replace() preg_replace() (i 修飾子を使う)
split() preg_split()、explode()、str_split()
spliti() preg_split() (i (PCRE_CASELESS) 修飾子を使う)

【対処方法 案1】
可能ならば全ての関数を代替え可能な関数や自作するなどして非推奨となる関数は使わないように対応します。

【対処方法 案2】
標準では非推奨の警告メッセージが表示されるだけで関数は動作するのでそのまま使い続ける案です。ただしこの対処は関数が削除されるPHP7.0.0からは使えなくなります。
ログファイルに以下の非推奨関数である旨の警告メッセージ出力されます。
「Deprecated: Function eregi() is deprecated in <ファイルパス> on line xxxxx.」
これが好ましくない場合は、PHP設定で非推奨メッセージは表示しないように調整することも可能です。例えば php.ini で

error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED

とするか、または

display_errors = On

としてもよいかと。

2.関数再定義はエラー

foo.php

Function a() { echo ‘common function’; }

bar.php

include(‘foo.php’);
Function a() { echo ‘override function’; }

このような構成で bar.php を実行すると関数a()が再定義されているとなってエラーとなります。
PHP4までは大丈夫だったのですが、PHP5からエラーチェックが厳密になりグローバル関数の再定義はエラーとなります。

【対処方法】
・require() ⇒ require_once() でインクルードすることで対処できる場合もあると思います。
または、
・関数定義側を
if(!function_exists(‘<関数名>’)){ } で囲む。こっちの方が機械的に対処可能です。

3.廃止されたmb○○○関数

PHP4ではmbstrlen()、mbsubstr()、 mbsubstr() などのマルチバイト文字列操作関数名を使用することができたかもしれませんが、
PHP5ではこれらは廃止となり、mb_strlen()、mb_substr()、 mb_substr() といった正式な関数名にしなければエラーとなります。

【対処方法】
・置換するか、旧い関数名で独自に定義するしかないですね。

4.型チェックが厳密

既存のレガシーシステムのPHP4に、以下のようなソースコードがあって、これまで動作していました。こんなやり方が流行った時期があるのでしょうか。

$db_connection = new MyDB();
・・・
if( strlen( $db_connection ) ) { <処理ブロックX> }

そもそもの実装として strlen を使ってオブジェクトが初期化されているかをチェックしているという作りがどうかと思います。PHP5になってから、このコードは警告メッセージが表示されて、たとえオブジェクトが初期化されていたとしても if文の中の<処理ブロックX>は処理されません。つまりPHPバージョンの違いによって全く違ったロジックで動くので注意が必要です。
PHP5からは、以下のワーニングが出ます。
PHP Warning: strlen() expects parameter 1 to be string, resource given in <ファイル名> on line xxx
【対処方法】
strlen()の場合、引数を文字列型(string)にキャストしてやるとエラーとはなりません。

if( strlen( (string)$db_connection )) { ..... }

5.register_globalsはもう使えません...

たぶん、そんな実装をやる人は今はもう居ないと思いますがレガシーなスクラッチ開発をしたWEBシステムには使われている場合があるんです。
PHPフレームワークを使うのが当たり前という世界の人には、全く無縁の機能です。
php.ini設定で
register_globals = On
ってやっておくと、たとえばフォームで、

<input name="”hoge”" type="”text”" value="”hoge”" />

とした入力項目のname属性をそのまま変数としてPHPプログラム内で $hoge のようにアクセスできるのです。
この機能はPHP5.4から削除されました。

【対処方法】
ソース書き換えしかないですね。
$hoge となっている箇所を $_POST[‘hoge’] とかに変える必要があります。いっそのことそれをいい機会とみて、フレームワークに乗り換えてもいいでしょう。

6.インスタンス変数の重複定義が厳しくなる

PHP4のコンパイラがゆるかっただけなのですが、以下のようにクラス内でプロパティ変数を重複してもコンパイルエラーにならなかったのですが、PHP5からはエラーとなります。

Class Hoge {
$foo = “”;
….
$foo = “override”;
}

次のようなエラーになります。

PHP Fatal error: Cannot redeclare Hoge::$foo in <ファイルパス> on line xxx

【対処方法】
重複しないようにソース書き換えです。

7.array_merge()関数の挙動の違い

引数のうち1つでも空(NULL)だった場合の挙動が変わります。
PHP4では引数の内1つでもNULLがあった場合でも、他の引数に配列が指定されていればそれらを連結して返します。
PHP5では引数の内1つでもNULLがあると、他の引数に配列が指定されていてもNULLを返します。

【対処方法】
引数にの1つでもNULLが渡ることを前提としている箇所は、この関数を呼び出す側でNULLが入らないように変更して動作を合わせる必要があります。

8.非推奨のサーバー変数を新しいものに変更する

HTTP_COOKIE_VARS に加えて、HTTP_POST_VARS、HTTP_GET_VARSといったサーバー変数が非推奨となりました。

【対処方法】
$_COOKIE,$_REQUEST,$_POST,$_GETを使うように変更。

以上になります。
実際の案件では上記のような要対応箇所が、数千ファイルからなるソースコードの中にどれくらい出現するかを検出するPHPのプログラムを作成して、工数の概算を算出するといったことも行いました。

タグ:
カテゴリー: PHP

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

カテゴリー