Fatal errorになる/ならない、PHP4とPHP5で違うこと

はじめに

いまさらですが、PHP4の環境に残されているシステムをPHP5へ移す作業を黙々としています。約10年くらい前のシステムなので、まぁ、なんというか、それだけいろいろな書かれ方をしているのです。そんな中で、PHP4でもPHP5でも「Fatal error」になりそうだけれど、そうでもない独特の解釈され方について、自分で「面白いなー」と思った点について書いてみたいと思います。

ケース1 : 複数の関数を同じ名前で定義したときの挙動

こんなコードがあるとします:

<?php

samename();

function samename() {
    echo "First!\n";
}

function samename() {
    echo "Second!\n";
}

同じ関数を2回定義しているので、PHPスクリプトとしてダメダメです。これを実行したときの反応を見てみます。

最初はPHP4で実行した場合です(ファイル名はw.phpとしています):

$ php w.php
First!
PHP Fatal error:  Cannot redeclare samename() (previously declared in /home/sakaki/w.php:6) in /home/sakaki/w.php on line 9

2個ある同じ名前の関数のうち、最初に出現する方が実行され、その後もう片方の関数の出現部分でFatal Errorが検出されます。

これをPHP5で実行すると以下のようになります:

$ php w.php
PHP Fatal error:  Cannot redeclare samename() (previously declared in /home/sakaki/w.php:6) in /home/sakaki/w.php on line 12

何も実行しないでエラーになります。

ケース2 : 複数の関数を同じ名前で定義したときの挙動 その2

続いてのコードです。こんなコードを用意してみました:

<?php

samename();
exit();

function samename() {
    echo "First!\n";
}

function samename() {
    echo "Second!\n";
}

途中で「exit();」が入っている点が違います。

これをPHP4で実行すると以下のような結果となります:

$ php w.php
First!

今度は同じ名前の関数のうち、先に現れた方を呼び出しながらエラーとなりません。「exit();」で終了するため、もう一つの関数定義にPHP4のインタープリターが気づかないためです。

このコードをPHP5で実行してみます:

$ php w.php
PHP Fatal error:  Cannot redeclare samename() (previously declared in /home/sakaki/w.php:7) in /home/sakaki/w.php on line 12

先ほどと同じように実行せずにエラーとなります。これは、最初の方を見ていれば予想通りかと思います。

まとめ

このように、PHP4では文法があっていればPHP5より緩くて通し、実行時にエラーとなるのですが、PHP5は厳しく見るのでパースでエラーとなって実行される前にエラーが出力されます。実際には「-l」オプションでlintを実行してみるとわかりやすいです。PHP4ではエラーを検出しませんが、PHP5ではエラーを検出します。

このコードのうち、実際に見かけたのは後者の形です。該当するスクリプトを作成した人は、エラーが出なかったために重複して同じ名前で関数を定義したことに気付かなかったのではないかと思われます。

こんなこともあるんだなぁ、ということでちょっとメモ代わりに書いてみました。

コメントを残す

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