PHP/FI 2.0 と PHP 3.0 の間における、知っておきたい変更点 ======================================================== 1998/01/14 堀田 倫英(翻訳) 誤訳のご指摘等は私までお願いします。 このファイルはタブサイズ4文字で見るようにデザインされています。 (訳注:タブは展開してしまったのであまり意味はありません) このファイルは4つのセクションに別れています: 1. 下位に対する言語の非互換性に関する変更。このセクションでは、PHP 3.0 を使う前にスクリプトの変更が必要になるような、核となる言語仕 様の変更内容の全てについて記述しています。ここには特定の関数の動 作についての変更点については記述されていません。 2. 新しい言語機能。このセクションでは、PHP 3.0 のためにデザインされ たスクリプトを活用するのに使われるであろう、核となる言語仕様に新 しく追加されたものについて記述しています。これも前記と同様に、関 数の動作についての変更点については記述されていません。 3. エンドユーザには直接には影響のない、構造的な変更部分。PHP 3.0 の 核となる部分は完全に書き直されました。このように、このバージョン では PHP/FI 2.0(のスクリプト)に影響を与える多くの点で、劇的に改 善されています。その結果、より安定し効率的な実装を行うことができ ました。 4. 前記のカテゴリにあてはまらない、その他の変更事項。 PHP 3.0 の核となる部分は完全に書き換えられたことを覚えておいてくださ い。またこのため、まだ私達が思い出せずにいる、どこにも言及されない非 互換部分があるかもしれません。もしここに記述されていない非互換性(ま たは新しい機能)があれば、私達 宛にメールし てください。 - Zeev ------------------------------------------------------------------------------ 下位に対する言語の非互換性に関する変更 ======================================= [1] PHP の閉じタグが > から ?> に変わりました。 これは と書くかわりに と書くようになったということです。 PHP3 ではまた、XML 準拠の長い書式の開始タグ が使えるようになりました。 短い開始タグ ('にメールでお知らせくださ い。また、文書化されていない PHP2 の機能のうち、PHP3 で動作しなく なったものについても情報をお待ちしています(たぶんサポートされな くなったということなんでしょうけど)。 ------------------------------------------------------------------------------ 言語仕様の新機能 ================ [1] 評価式 PHP 3.0 では、2.0 に比べて先進的で充実した評価式の実装がなされて います。たとえば複雑な C や perl ライクな評価式も動作します。代入 演算子(+=, -=, *= など)、前置や後置インクリメント/デクリメント (すなわち $i++, ++$i)および3項演算子( (式?式:式))などのサポー トが追加されました。現在はどの代入式においても、値を伴う式つまり $a = $b = $c = $d = 0; などが使えます。べき乗の式を数行のコードで 書くのは難しいものですが、あなたがもしこういったコードを書き慣れ ているのであれば、おそらくどういったコードになるかを思い浮かべる ことができるはずです。 [2] for ループのサポート for ループは実装することがかなり難しいものでした(実際、今までに for ループをサポートした同等のインタプリタにお目にかかったことは ありません(いいえ、perl はインタプリタじゃありませんよ)。for ル ープの動作は while ループに比べて 5% ほど遅くなりますが、よりスマ ートに書けます。 書式は C と同様です: for (式; 式; 式) ステートメント; または for (式; 式; 式) { ステートメント ... } ループに制御が移るとまず1番目の式が実行され、2番目の式が TRUE である と評価される限りループが実行されます。また繰り返しのたびに3番目の式が 評価されます。 コロンモードの for ループもサポートされます: for (式; 式; 式): ステートメント ... endfor; [3] do..while(式) ループのサポート このループに処理が移ると、C と同様に、do..while ループの内部にあるステ ートメントが最初1回実行されます。その後評価式が true であると評価され ている間このステートメントが実行されつづけます。 例: do { ステートメント; } while ($i++ < $max); [4] ループ内部における break と continue ステートメントのサポート これらのステートメントを使って、ループの途中から抜けたり、次の繰 り返しから続行したりすることができます。PHP 特有の機能として、 break や continue に対して引数を指定することができます。これは、 break で抜けたり continue で継続したいループの数を指定します。 以下に例を示します: for ($i=0; $i<10; $i++) { for ($j=0; $j<10; $j++) { if ($j>5) break; if ($i>5) break 2; } } 最初の break ステートメントは、$j が 5 を超えるたびに内側のループを 終わらせます。2番目の break ステートメントは、$i が 5 を超えたときに 両方のループを終わらせます。 注意:ちなみに、switch ステートメントはループであるとみなされます。 もし switch ステートメントの内部に "break 2;" と記述すると、その switch から抜け、さらにネストした一番内側のループから抜けることになります。 [5] 関数が C スタイルの宣言になりました このよい例となる、あまり意味のない関数を示します。 function concat($str1,$str2) { return $str1.$str2; } 注意:以前の PHP/FI スクリプトをアップグレードできるように、昔の スタイルの関数定義もまだサポートされています。古いスタイルの関数 を使う場合は、単に 'function' を 'old_function' に変更してくださ い。 [6] OOP サポート PHP 3.0 では限定的ではありますが、クラスと継承がサポートされています。 単純なクラスの宣言の例を以下に示します: class simple_class { var $property1,$property2; var $property3=5; function display() { printf("p1=%d, p2=%d, p3=%d\n", $this->property1, $this->property2, $this->property3); } function init($p1,$p2) { $this->property1 = $p1; $this->property2 = $p2; } }; このクラスのオブジェクトを生成するには、以下のようにします: $obj = new simple_class; この時点で $obj は、 2 つの初期化されていない変数、1 つの初期化された 変数、および 2 つのメンバー関数を持つオブジェクトとなります。オブジェ クトの内部ではいっさいの保護はなされず、そのプロパティへのアクセスは 簡単です: $obj->property1 = 7; は $obj の中の $property1 に 7 を代入します。メンバ関数のコールも簡単 にできます: $obj->display() は $obj の display() メンバ関数を実行します。display() の実装では 特別な変数 $this を使っていることに注意してください。これは、関数 がコールされたオブジェクトに置きかえられます。 継承もまたかなり簡単です: class complex_class extends simple_class { var $property4="test"; function display() { printf("p1=%d, p2=%d, p3=%d, p4=%d\n", $this->property1, $this->property2, $this->property3, $this->property4); } } 基本的にクラス complex_class はその親である simple_class からすべてを 継承しますが、親のものをオーバーライドするメンバー関数だけは別です。 この例では別の display() 関数を提供していますので、simple_class で宣言 された display() 関数ではなく complex_class オブジェクトの関数が使われ ます。一方、ここでは init() 関数は宣言していないので、simple_class の オブジェクトと同様に、complex_class のオブジェクトは同じ init() 関数を 持つことになります。 このことから、OOP を 2,3 行で記述するのは不可能であることがわかります。 個人的には、これらを日常的なスクリプト記述にどうやって活用していけば いいのかが、はっきり言ってよくわかりません。この記述が気に入った場合は、 使いものになるまで遊んでみてください :) オブジェクトを配列内に持つことも、オブジェクト内に配列を持つことも できます。しかしながら、現在の実装の制限ではオブジェクトの内部に オブジェクトの配列を持つことはできません(実際には許されているので すが、そのようなオブジェクト・プロパティを、直接的にも間接的にも アドレッシングすることができないのです)。たとえば $a[3] がオブジ ェクトで、$a[3]->b[2] もオブジェクトだとすると、$a[3]->b[2] のプロ パティを指定することはできません(すなわち、たとえば $a[3]->b[2]->foo = "bar" と書くことはできないということです)。 [7] 関数ポインタがサポートされました A simple illustrative example: 簡単な例を示すと、 $func_ptr = "time"; $current_time = $func_ptr(); と $current_time = time(); とは同等です。 [8] 間接参照がより強力になりました たとえば、$ 演算子を無限回数使ったとします。 $a = "b"; $b = "c"; $c = "d"; $d = "e"; $e = "Testing\n"; echo $$$$$a; これは $e の内容、すなわち "Testing\n" を表示します。 加えて、perl ライクな書式で変数名を生成するのに $i="123"; ${"test".$i} = 5; のような複雑な式をつかっても、ちゃんと $test123 に 5 が代入されます。 [9] 文字列連結演算子が追加され、'+' ではもはや文字列を連結しません。 perl ライクな文字列連結演算子 '.' が追加されました。これはその両辺を 文字列に変換し、それらを連結します。たとえば、 $result = "abcd".5; は result に "abcd5" を代入します。PHP 3.0 においては、'+' 演算子は その両辺が文字列であっても、もはや連結を行わないので注意してください。 そのかわりに '.' を使用してください。 [10] 関数への引数の渡し方で、値渡しだけでなく参照渡しもサポートされました 関数への引数の渡し方で、値渡しだけでなく参照渡しもサポートされました。 これは関数の実装においてはなんら変化がありませんが、その関数をコール する際に、渡した変数が関数により実際に変更されるのか、それとも変数の コピーを渡すのかを選べます。 例: function inc($arg) { $arg++; } $i=0; inc($i); # 外側のスコープにある $i は変更されず、0 のままです。 inc(&$i); # $i は参照渡しされ、1 に変わります。 [11] 多次元配列のサポート (または Andi の言葉を借りると '超次元配列') PHP 3.0 でサポートされたこの機能を定義する一番簡単な方法は、帰納 法を使うことです。配列はいろいろな型の変数から構成でき、それには 他の配列を含むこともできます。簡単な例を示します: $a[0]=5; $a[1]["testing"]=17; $b["foo"]=$a; あれ、あまり簡単じゃなかったでしょうか?まあ、遊んでみてください。 とても強力な機能ですよ。 [12] 配列の初期化がサポートされました。 たとえば、数字から月の名前に変換するために検索テーブルを初期化し たいとします。 $months = array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); このコードは $month[0] を January, $month[1] を February といった 具合に代入します。また、配列の開始番号を 0 ではなく 1 にしたい場合 は、 $months = array(1=>"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); のようにします。また、先頭のエントリだけでなくすべてのエントリに インデックスを付けることもできます。 $first_names = array("Doe"=>"John", "Gates"=>"William", "Clinton"=>"Bill" }); は $first_names["Doe"]="John" などのように代入します。 [13] Perl スタイルのリストがサポートされました。 配列が持つ複数の値を、1つのステートメントで複数の変数に代入する ことができるようになりました。たとえば: $str = "johndoe:x:555:555:Doe, John:/home/johndoe:/bin/tcsh"; list($username,$passwd,$uid,$gid,$realname,$homedir,$shell) = explode(":",$str); は 'johndoe' を $username に、'x' を $passwd に代入します(以降も 同様)。 [14] コロンが 'case' ステートメントと 'default' ステートメントで サポートされました。 例: switch($value) { case 'A': statement; break; case 'B': statement; break; case 'C': statement; /* fall-through */ default: statement; } セミコロンもなおまだサポートされてはいますが、新しいスクリプトを 書く場合はコロンを使うことが推奨されています。 ------------------------------------------------------------------------------ 言語仕様には関係しない新機能 ============================ [1] 永続的なリソースリスト これは SQL ドライバを書くのに便利な機能で、これにより毎回 SQL リ ンクのオープンやクローズをやる必要がなくなります。最初に必要にな ったときにオープンしておいて、それ以降随時そのリンクを使うことが できるというものです。PHP 3.0a1 の時点では、MySQL, mSQL, PostgreSQL ドライバがこのオプションを使うように書き直されました。これを使用 するには、mysql_connect() の代わりに mysql_pconnect() を使います (その他のデータベースでも同じようにします)。 [2] 設定ファイル. PHP はそれ自身の設定ファイルを持つようになりました。これにより、 PHP2 における多くのコンパイル時オプションが、実行時に指定できるよ うになりました。 [3] 文法の強調表示 PHP 3.0 では文法の強調表示機能が組み込まれました。つまり、あなた のコードを実行するかわりに、文法を強調表示した形でコードの表示が おこなえるようになったということです。これを行うには2つの方法が あります。1つは show_source() ステートメントを使うことです。こ のステートメントは include() ステートメントまったく同じですが、た だしそのファイルを実行するのではなく、文法を強調してそのソースを 表示します。 2番目の方法は、 apache モジュールとして実行している場合にのみ可 能なのですが、PHP 3.0 のソースファイルに対して特殊な拡張子(すな わち .php3s)をつけてやることです。こうすると、apache は自動的に そのファイルを文法を強調して表示します。 [4] ローダブル・モジュール これは Windows バージョンでは非常にインパクトのありそううなことで すが、UNIX 環境でも同様に使われることでしょう。ダイナミック・モジ ュールをローディングすることにより、PHP の内部関数を実行時に追加す ることができるようになりました。現時点では、これは Solaris, Linux および Win32 で動作することが知られていますが、非互換性が見つかれ ば、それ以外の可能なプラットフォームにも移植されてゆくことでしょう。 ------------------------------------------------------------------------------ その他、目を引く項目 ======================== [1] 改善されたパフォーマンス PHP 3.0 においては、PHP/FI 2.0 よりもパフォーマンスがかなり改善さ れています。Apache のメモリ・プールではなく内部のメモリ・マネージ ャを使うことにより、多くのケースでメモリの消費量が劇的に減少して います。速度的には PHP/FI 2.0 の2倍から3倍になっています。 [2] より信頼性の高いパーサ PHP 3.0 がきちんとテストされた今、そのパーサは PHP 2.0 のそれに比 べてかなり信頼性があるということができます。PHP 2.0 においても、 単純なスクリプトや相当複雑なスクリプトをかなりうまく処理してきた のですが、PHP 3.0 に比べるとエラーになりやすかったのは確かです。 PHP 3.0 では、あまり知られていないパーサの問題がかなり少なくなっ ています。 [3] 改善された C API もしあなたが C のプログラマなら、PHP に機能を追加することはけっし て簡単なことではありませんでした。かなりきちんと文書化された API が使えるようになり(apidoc.txt) 、もはや関数を追加するためにパーサ やスキャナに手を入れる必要はなくなりました。また(保全のためのスタ ックを持たない)PHP2 の時に比べて、PHP3 関数を実装する際に '固まっ てしまう'ことは少なくなりました。しかしもちろん、その可能性は 0で はありません:-) [4] 名前の変更 PHP/FI 2.0 は PHP 3.0 と名前を変え、その意味も 'Personal Home Pages / Forms Interpreter' から 'PHP: Hypertext Preprocessor' へ と変わりました。'Personal' なホームページは PHP/FI 2.0 に対して控 えめ付けられた名前でしたが、PHP 3.0 がリリースされるにいたっては、 PHP/FI 2.0 は文字通り控えめなものになってしまいました。