PHP6の新機能 備忘録まとめ1

PHP6の正式版のリリースが待たれていますが、現在多くのプログラムはバージョン4、5で稼動しています。
一部のサーバではPHP4からPHP5への移行を行っていますが、いまだにPHP4,5は現役と言えるでしょう。
しかし、PHP6のリリースでPHP4,5,6と環境が3つになると管理が面倒になります。
少なくとも、私は未だPHP6というものをよく知りません。
そこで、今回はPHP6について新機能を備忘録として記載しておくことにしました。

PHP 6の新機能のうち、言語仕様の面で大きな変化となるのが「namespace」と呼ばれる機能です。
直訳すると一般に「名前空間」と訳されますが、簡単に言うとクラス名や関数名の衝突を防ぐことを目的とした機能です。

例えば、あるPHPスクリプトAで、外部のファイルに記述されたクラスや関数ライブラリをincludeやrequireで読み込んでいるとします。
また、このPHPスクリプトのファイル中にも、関数Fが記述されている場合、「Fatal error: Cannot redeclare F() (previously declared in A.php:5) in B.php」と怒られてしまいます。

小規模なスクリプトなら、全体が把握しやすく名前も管理しやすいのですが、最近はPHPも大規模なシステムに採用されることがあるので名前の管理が難しくなってきました。
大規模だと複数のプログラマが並行で作業しつつ、名前が重複しないようにするためには、あらかじめきちんと命名規則を定める必要があります。
また、システムの規模が大きくなれば、それだけ名前が重複する可能性も高くなりますので、名前自体がどんどん長くわかりにくくなってしまいます。
こういった問題は、PHPで使われる「関数名」や「クラスメソッド名」が、常に「グローバルな空間」という大きな単位で扱われるために起きます。
そこで、ひとつの「名前」が有効な空間をより小さな単位に分割し、プログラマが容易に把握できる範囲に閉じこめるための機能が「名前空間」なのです。

先ほどの例で言うと、明示的に指定しない限り、A.phpのF関数と、B.phpのF関数は、共にグローバルな名前空間の「F関数」であり、区別がつきません。
しかし、それぞれのスクリプトが、各々別の名前空間を持てば、この問題は解決できるはずです。
PHP 6で追加された名前空間の機能では、「namespace 名前空間名;」で、個別に名前空間を宣言することができます。
名前空間が別々に分離されたことで、このスクリプトはエラーを起こさずに実行されます。
名前空間を指定せずに関数を実行した場合、呼び出し元と同じ名前空間内にある関数が実行されます。

名前空間と並ぶPHP 6の大きな変更点として、「国際化対応」があります。
「ん? これまでもmbstringがあったじゃん」と思われるかもしれませんが、mbstringはあくまでもエクステンション。
つまり拡張機能であって、 PHP本体の機能ではありませんでした。
もちろん、我々マルチバイト文字言語圏の住人にとって、mbstring拡張は欠かせない機能です。
しかし、英語圏を中心としたISO-8859-1エンコーディングしか使わない人たちにしてみれば、無用な機能でしかありません。
事実、mbstring拡張のインストールで悩まされたこともありました。
しかし、PHP 6からはPHP本体に国際化の機能が実装されるため、マルチバイト言語の基本的な処理に関しては、我々もより安心して利用できるようになりそうです。
さて、このPHP 6の国際化機能は、主に「ICU (International Components for Unicode)」ライブラリを利用して実装されています。
ICUは、IBMが提供するUnicodeと国際化処理のためのC/C++、Java向けライブラリで、オープンソースライセンスの下で配布されています。
文字エンコーディング変換、日付や通貨の書式変換、ユニコード対応の正規表現などの機能が必要なアプリケーション開発では標準的に利用されているそうです。
PHP 6では、ソースコードからのビルド時に、あらかじめICUライブラリがインストールされていることが要求されます。
組み込まれているICUのバージョン等は、phpinfo()関数の出力結果に表示されますので、一度確認してみるとよいでしょう。

php.iniのUnicode設定に関する主なディレクティブは、それぞれ以下のような意味を持ちます。
* 「unicode.semantics」: Unicode機能の有効・無効を切り替えます
* 「unicode.runtime_encoding」: 関数の引数、文字列連結、比較など、PHPスクリプトの実行時に内部的にバイナリ文字列を変換する際に使用するエンコーディングを指定します
* 「unicode.script_encoding」: スクリプトの記述に使用するエンコーディング
* 「unicode.output_encoding」: 出力エンコーディング。
mbstring拡張では出力バッファを利用してエンコーディングの変換を行っていましたが、PHP 6ではechoやprintで出力されるデータが、この設定に従って自動的に変換されます

これまでのPHPでは、国際化対応があくまでもエクステンションのレベルで行われていたため、言語自体のもつコアな関数には、マルチバイト文字について考慮されていないものも多々ありました。
例えば、文字列を構成する「文字数」を返す「strlen」は、マルチバイト文字を引数にした場合に、文字数ではなくバイト数を返してしまいます。

ソフトウェアの「国際化」といった場合、各国の言語で使用される「文字」を正しく扱うための「UNICODEサポート」は、もちろん最重要の課題といえるでしょう。
しかし、お国柄で異なるのは、なにも「文字」だけではありません。
例えば「通貨」は、国(もしくは特定の経済圏)によって「ドル」だったり「ユーロ」だったり、「元」だったり「円」だったりします。
「日付」も、日本では「2008/11/20」のように「年/月/日」で表記するのが普通ですが、アメリカでは「Nov. 20, 2008」や「11. 20, 2008」のように「月. 日, 年」で表記することも多いようです。
さらにややこしいことに、ヨーロッパでは「20/11/2008」のように「日/月/年」となります。
同じ英語の国でも、アメリカとイギリスでは日付の月と日の順序を逆に表記しているわけですね。
他にも、「メートル」と「インチ」といった長さの単位、「キロ」「グラム」「ポンド」「オンス」「匁」といった重さの単位も国によって異なります。
また、日本国内だけでも「あいうえお順」「いろは順」があるように、データを並び替える際の順序も様々です。
数値の表現形式も、ドイツのように「小数点」が「. (ドット)」ではなく「, (カンマ)」になる国もあります。
このようにソフトウェアの「国際化」というのは、その国の文字だけ表示できればよいという単純なものではなく、それぞれの国や地域の人々が長年に渡って育んできた「文化」や「慣習」を取り入れ、どこの国の人でも違和感なく使える仕組みを作らねばならないという、非常に厄介なテーマなわけです。
こういったややこしい問題の解決手段が、いわゆる「ロケール」の機能になります。
PHP 6で標準搭載になる国際化ライブラリ「ICU」は、UNICODE処理のための機能以外にロケールを扱うための機能も持っており、PHP 6のロケール対応も、このICUの機能をラッピングする形で提供されることになります。
今のところ、PHP 6のロケール対応については情報がまだそれほど多くありませんが、拡張モジュールの形では、ICUラッパー「国際化(Intl)エクステンション」が既に PHPには用意されています。
このエクステンションを導入することで、PHP 5でもICUの以下の機能を活用できるようになります。

1.
Locale: 「ロケール識別子」を扱う機能です。
ICUでは、ロケール識別子としてRFC 4646で提案されている言語タグを使用します。
言語タグの正確な仕様についてはRFCをきちんと理解しなければいけませんが、基本的には「言語-地域」のように「言語」「地域」といったサブタグをハイフンで連結して並べたものと考えればよいでしょう。
日本語で地域が日本なら「ja-JP」英語でアメリカなら「en-US」といった具合です
2.
Collator: ロケールに応じた並び順を決めるための文字列比較の機能です
3.
Number Formatter: ロケールに応じた書式で、数値や通貨を表示したり解釈したりするための機能です
4.
IntlDateFormatter: ロケールに応じた書式で、日付時刻を表示したり解釈したりするための機能です
5.
Message Formatter: ロケールに応じて、数値や日付を含むメッセージを柔軟に翻訳できるようにするための機能です
6.
Normalizer: 保存形式を統一しておくなどの目的から、文字列をあらかじめ定められた統一形式に「正規化」する機能です

昨今、日本国内で展開しているWEBサービスを海外でも展開していきたいという要望を出されるケースが増えてきています。
ロケールの機能を上手く使いこなせば、あらかじめこういった要望が出ることを想定した開発もできますし、それによって必要工数・コストが激増するといった心配もありません。
国際的な活躍を目指すPHPプログラマには、これから特に注目していてもらいたい機能のひとつと言えるでしょう。

PHP 6の大きな目玉はICUによる「国際化」ですが、開発の現場や既にPHPが稼働しているWebサイトでは、そのほかの細かい変更も結構重要だったりします。

(1) register_globalsが廃止
昔のPHPでは、クライアントからPOST/GET/COOKIEで渡されるデータを、そのまま名前の頭に「$」をつけた変数として扱えるのが普通でした。
例えばWebブラウザに表示されたフォームで「<input name=”email” type=”text” />」という要素があれば、そこに入力された値は、PHPでは自動的に「$email」として参照できたのです。
このわかりやすさ、カンタンさは、PHPスクリプト開発者を激増させることに大きく貢献しましたが、その一方で、セキュリティ面に問題のあるスクリプトが量産される原因にもなってしまいました。
そこでPHP 4.2.0以降では、php.iniの「register_globals」パラメータがデフォルトOffに設定され、明示的にOnに変更しない限りはフォームのemailは$emailに展開されなくなりました。
PHP 6では、このregister_globalsパラメータ自体が廃止になります。
register_globals=Onを前提に書かれているスクリプトは動作しなくなりますので、古いアプリケーションは必ず見直しをしておきましょう。

(2) magic_quotes_gpc
magic_quotes_gpcも、register_globalsと同様に廃止されます。
この機能はPOST/GET/COOKIEでPHP スクリプトに渡されるデータ中の、引用符等を自動的にエスケープするものでした。
SQLインジェクションを防ぐには効果的な機能でしたが、無駄にエスケープされるデータが多くパフォーマンスを犠牲にすることや、スクリプトの移植性が低下することなどから、開発者の間では敬遠され続けてきた機能でもあります。

(3) safe_mode
共有レンタルサーバ等でよく使われてきた「セーフモード」も廃止です。
セーフモードという名称から「セキュリティを確保してくれる機能」と誤解されがちですが、実際はあくまでもスクリプトのバグに対する「フェイルセーフ」の機能に過ぎません。
つまり、これを過信されると余計に危ない、ということでしょう。
サーバ管理者の皆さんは、PHPスクリプトを安全に運用するための実装手段について、この機会にもう一度検討してみるとよいでしょう。
意外と、安全と信じていた従来の構成に穴が見つかったりするかもしれません。

(4) zend.ze1_compatibility_mode
PHP 4からPHP 5へのバージョンアップ時に、オブジェクト型の変数の代入時のデフォルトの動作「値渡し」から「参照渡し」になる等の変更が行われました。
このパラメータは、PHP 4からPHP 5への移行をスムーズにするために用意されたものなので、PHP 6では削除される方向です。

(5) Freetype 1とGD 1
PHPは、描画ライブラリのGD、フォントエンジンのFreetypeを使って、グラフ等を動的に生成することができますが、PHP 6では、Freetype、GDそれぞれの旧バージョンがサポートから外れます。

(6) register_long_arrays
HTTP_POST_VARS、HTTP_GET_VARS等も廃止の方向です。
これらの配列は昔の名残で残されていますが、結局中身は「$_POST」や「$_GET」と重複しています。
register_globalsと同様に、古いアプリケーションはそろそろ見直しておきましょう。

(7) GOTO文のサポート
筆者には必要性が全く理解できないのですが、PHP 6ではGOTO文がサポートされます。
GOTO文は、実行途中でいきなり指定された「ラベル」の場所に処理をジャンプさせます。
エラー処理などでは便利とも言えますが、GOTO文を使わなくてもエラー処理は書けますし、昔からスパゲッティプログラムの元凶と言われてきた GOTO文を、わざわざ今の時代に復活させる意味があるのかどうか。
もちろん、プログラムがスパゲッティ化するのはGOTOという言語仕様がいけないのではなくて、その使い方が下手なだけというのは理解できるのですが……。
まあ、追加された機能を全て使わなければいけないわけでもないので、プロジェクト毎に標準規則で「使う/使わない」を決めればよいでしょう。