PHP/FI 2.0 から PHP 3.0 への移行

3.0 における互換性

PHP 3.0 は 1 から書き直されました。これには 2.0 のパーサに比べて より堅牢で一貫性のある適切なパーサが内蔵されています。3.0 はまた、 劇的に速くなり、メモリ消費量も少なくなっています。しかしながら、 これらの改善事項のうちのいくつかは、書式と機能の両面において 互換性を欠いた変更になってしまっています。

加えて、PHP の開発者は、PHP 3.0 における書式と意味の双方をきれいに し直そうとしましたが、これも互換性を欠く要因となっています。長い目 で見れば、これらの変更はより良いものであると私たちは信じています。

この章では、あなたが PHP/FI 2.0 から PHP 3.0 へ移行する際に遭遇 するであろう非互換性と、それらへの解決策についてのガイドを提供 しようと思います。必要でない限り、新しい機能については述べられて いません。

あなたの古い PHP/FI 2.0 スクリプトを自動的に変換できる変換プログラム があります。これは PHP 3.0 ディストリビューションの convertor サブディレクトリ にあります。このプログラムは文法的な変更を捕らえるだけですので、 どちらにしてもこの章を注意深く読む必要があるでしょう。

開始/終了タグ

PHP の開始と終了のタグが変わっていることに、おそらく最初に気付かれる でしょう。古い <? > 形式は、3 つの新しい 形式に置き換えられました。

例 A-1移行:古い開始/終了タグ


<? echo "これは PHP/FI 2.0 のコードです。\n"; >
      
バージョン 2.0 で、PHP/FI は次のバリエーションもサポートするように なりました。

例 A-2移行:最初の新しい開始/終了タグ


<? echo "これは PHP 3.0 のコードです!\n"; ?>
      
終了タグは、単なる '>' に代わり '?>' で構成されます。しかし ながら、サーバ上で XML を使いたい場合は、この最初の形式では不具合 が生じるでしょう。なぜなら、PHP は XML ドキュメントの中の XML マークアップを PHP コードとして実行しようとするかもしれないからです。 このため、以下のバリエーションが導入されました。

例 A-3移行:2 番目の新しい開始/終了タグ


<?php echo "これは PHP 3.0 のコードです!\n"; ?>
      
エディタ上で、処理している命令タグが全く認識されないという問題が 発生した方がいました。Microsoft FrontPage はそんなエディタのうちの 1 つです。これらを回避するため、さらに以下のバリエーションが導入 されました。

例 A-4移行:3 番目の新しい開始/終了タグ


<script language="php">

  echo "これは PHP 3.0 のコードです!\n";

</script>
      

if..endif の文法

if(); elseif(); else; endif; を使って if/elseif/else ステートメントを 記述するための '選択肢' については、3.0 パーサに対してかなり複雑な処理 を追加してやらないと、効率的な実装を行うことができません。このため、 文法が変更されました。

例 A-5移行:古い if..endif の文法


if ($foo);
    echo "はい\n";
elseif ($bar);
    echo "だいたい\n";
else;
    echo "いいえ\n";
endif;
      

例 A-6移行:新しい if..endif の文法


if ($foo):
    echo "はい\n";
elseif ($bar):
    echo "だいたい\n";
else:
    echo "いいえ\n";
endif;
      
評価式を終了させるもの(endif)を除き、すべてのステートメントにおいて セミコロンはコロンに変更されました。

while の文法

if..endif と同様に、while..endwhile の文法も変更されました。

例 A-7移行:古い while..endwhile の文法


while ($more_to_come);
    ...
endwhile;
      

例 A-8移行:新しい while..endwhile の文法


while ($more_to_come):
    ...
endwhile;
      

警告

PHP 3.0 で古い形式の while..endwhile を使った場合は、無限ループ になってしまいます。

式の型

PHP/FI 2.0 では、結果の型を決めるのに左辺式を使っていました。 PHP 3.0 では、結果の型を決めるのに両辺を使うようになったので、 3.0 環境の元で 2.0 のスクリプトを実行すると、予期しない結果になる 場合があります。

以下の例を考えてみましょう。


$a[0]=5;
$a[1]=7;

$key = key($a);
while ("" != $key) {
    echo "$keyn";
    next($a);
}
      

PHP/FI 2.0 では、この例は $a の 2 つのインデックス双方を表示します。 一方、PHP 3.0 ではなにも表示されません。この理由は、PHP 2.0 では、 左側の引数が文字列なので文字列の比較が行われますが、もちろん """0" とは等しくならない ためです。一方 PHP 3.0 では、文字列が数字と比較されると、(文字列 が数字に変換され、)数字による比較が行われます。0atoi("") で比較され、さらに変数リスト の方も 0 と評価され、0==0 なので、その結果ループは 1 度も実行されないということに なります。

これを解決するのは簡単です。while ステートメントを以下のように変更 します。


while ((string)$key != "") {
      

エラーメッセージの変更

PHP 3.0 のエラーメッセージは、2.0 よりも通常の場合正確になりました。 しかし、もはやソースコードのうちエラー原因となった部分は表示されません。 そのかわり、エラーの原因となったファイル名と行番号が表示されるので、 驚くかもしれません。

短絡的なブール評価

PHP 3.0 におけるブール評価は短絡的です。というのは、 (1 || test_me()) のような評価式があるとすると、関数 test_me() は実行されないということです。これは、 1 を評価した後は、最終的な評価結果を変えることは できないと分かっているからです。

これは互換性の問題としては些細なことかもしれませんが、思わぬ副作用 があるかもしれません。

関数の TRUE/false 返り値

ほとんどの内部関数が書き直されたのに伴い、PHP/FI 2.0 では成功時に 0 、失敗時に -1 を返していたのが、それぞれ TRUEFALSE を返す ように変更されました。この新しい振る舞いにより、 $fp = fopen("/your/file") だとか fail("darn!"); のような より論理的なコードを書く事ができるようになりました。PHP/FI 2.0 には、関数がその実行に失敗した時に何を返すべきかという明瞭な ルールがなかったので、そのようなスクリプトのほとんどは、2.0 から 3.0 のコンバータを使った後に、手作業でチェックしなければならないと 思います。

例 A-92.0 からの移行:返り値、古いコード


$fp = fopen($file, "r");
if ($fp == -1);
    echo("$file を読み込み用として開くことができませんでした<br>\n");
endif;
      

例 A-102.0 からの移行:返り値、新しいコード


$fp = @fopen($file, "r") or 
  print("$file を読み込み用として開くことができませんでした<br>\n");
      

その他の互換性

例 A-112.0 からの移行:文字列の連結


echo "1" + "1";
     

PHP 2.0 ではこれで 11 が表示されますが、PHP 3.0 ではこれは 2 になります。代わりに次のようにして下さい。

echo "1"."1";
      

$a = 1;
$b = 1;
echo $a + $b;
      

これは PHP 2.0 でも 3.0 でも 2 になります。

$a = 1;
$b = 1;
echo $a.$b;
      
これは PHP 3.0 では 11 になります。