PHP 5.6の新機能

Computer, Programming 12月 3, 2013 #PHP
(Last Updated On: )

PHP Advent Calender 2013、3日目の参加エントリです。前日のPHP の配列を使った手品とその種明かしに続き3日目です。PHPの配列(ハッシュ)のキーはバイナリセーフなので何でも入れられる、ということはあまり知られていないですよね。面白い話だったと思います。

私のネタには面白さはありません。予めご了承ください :-)

さて今日のテーマのPHP5.6新機能です。PHPプロジェクトのgitレポジトリでは既にPHP5.6用のブランチが作成されています。PHP 5.6は来春リリース予定です。

大ニュース(?)だったので多くの方はご存知だと思いますが、PHPは毎年新しいマイナーバージョンをリリースします。メンテナンスされるのは2つのバージョンのみです。つまりPHP 5.6がリリースされるとPHP 5.4はEOL(メンテナンス停止。+1年のセキュリティフィックスのみ)になります。来春にPHP 5.3は完全終了です。皆さん、準備はできているでしょうか?(まだまだ色々機能を付けなければなりませんが、個人的にも困るのでアップグレードを容易にするPROVE for PHPというツールを開発しています。よろしければ試用してみてください。)

前置きが長くなりましたがPHP 5.6の新機能を紹介します。

 

PHP 5.6の新機能&仕様変更

1年ごとの定期アップグレードに変わったので、それほど大きな機能追加はありません。

知っている方も多いと思いますが、新しいPHPの新機能はgitレポジトリのUPGRADINGファイルを見ると分かります。検討中の新機能はWikiのRFCページで参照できます。

仕様変更

リリースまでに更に新しい機能や仕様変更が行われますがUPGRADINGに記載されている仕様変更と新機能は以下の通りです。

========================================
1. Backward Incompatible Changes
========================================
– Core:
  Removed $HTTP_RAW_POST_DATA global variable. Restore backwards compatibility
  by:
  <?php
  global $HTTP_RAW_POST_DATA;
  if (!isset($HTTP_RAW_POST_DATA)) {
      $HTTP_RAW_POST_DATA = file_get_contents(“php://input”);
  }
  ?>
– JSON:
  json_decode() no longer accepts non-lowercase variants of lone JSON true,
  false or null values. For example, True or FALSE will now cause json_decode to
  return NULL and set an error value you can fetch with json_last_error().
  This affects JSON texts consisting solely of true, false or null. Text
  containing non-lowercase values inside JSON arrays or objects has never been
  accepted.

この情報は2013/12/2時点のgitの内容ですが、既にもう古くなっています。

グローバル変数の$HTTP_RAW_POST_DATAが削除された、と記載されていますが実際にはphp.iniのalways_populate_raw_post_data=Onに設定すると、従来通り初期化されます。

json_decode() が ”true” “false” “null” と書かないと論理値/ヌル値として認識せず、エラーとなります。そもそも、大文字を使う意味がないので影響を受けるユーザーはほぼ居ないと思います。

 

新機能

次に新機能です。

========================================
2. New Features
========================================
– Added dedicated syntax for variadic functions.
  (https://wiki.php.net/rfc/variadics)
– The php://input stream is now re-usable and can be used concurrently with
  enable_post_data_reading=0.
– Added gost-crypto (CryptoPro S-box) hash algo.
– Added openssl certificate fingerprint support (inclusive stream context
  option).
– Added openssl crypto method stream context option.

Variadic

パラメーター数が可変である関数・メソッドであることをシグニチャに明記できるようになるvariadicが追加されます。次のように利用します。

function fn($reqParam, $optParam = null, ...$params) {
    var_dump($reqParam, $optParam, $params);
}

fn(1);             // 1, null, []
fn(1, 2);          // 1, 2, []
fn(1, 2, 3);       // 1, 2, [3]
fn(1, 2, 3, 4);    // 1, 2, [3, 4]
fn(1, 2, 3, 4, 5); // 1, 2, [3, 4, 5]

C言語の場合、可変引数の場合は “…” と標記します。それに似た標記です。他の引数と同じで&を前に付ければ参照渡しにもできます。(例: &…$params)

「これで何が便利なの?」を思うかも知れませんが、関数・メソッドが可変であることが関数定義を見るだけで分かります!IDEなどで関数定義を参照するだけで「可変数の引数を取る関数」と分かるメリットは大きいです。

更に可変部分の引数は配列として渡されます。つまり、そのままforeachなどで追加引数を処理できるようになります。多少面倒だった可変引数関数の処理が楽に行えるようになります。

POSTデータサイズが無制限

– The php://input stream is now re-usable and can be used concurrently with
  enable_post_data_reading=0.

この変更は$HTTP_RAW_POST_DATAが削除される(実際には削除されないが、非推奨)とした変更と関連しています。PHPは巨大なPOSTデータが送信された場合でも、メモリに保存するので大きなPOSTデータ処理には向きませんでした。しかし、この変更でPHPが$_POST, $_FILESに保存しない形式の場合、デフォルトではPOSTデータはメモリに保存されなくなりました。更に2GBまでのPOSTデータしか取り扱えませんでしたが、64bit化されたので事実上無制限になります!PHP 5.6からはどんな大きなPOSTデータでもどんとこい、です。更にこのノートに書いてあるように、必要に応じてphp://input (つまりPOSTデータ)を何度も、しかも別のコードから同時に読みだしても大丈夫になっています。

OpenSSL

OpenSSLの追加はUPGRADINGに書いてある通りです。

constに表現

UPGRADINGにはまだ書いていないですが、constに表現が使えるようになりました。define()の場合は関数の戻り値/$_GET/$_POSTの値、何でもOKでしたが、constは

const  myconst = 60 * 60 * 24;

とすることで出来ませんでした。PHP 5.6から可能になります。他のconst定数を利用して

const myconst = a * 20;

等とすることもできるようになります。

無効な呼び出しの禁止

以下のコードはスタティックメソッドでないfoo()をスタティックに呼び出しています。

class A { function foo() {} }
A::foo(); // E_STRICT

これは$thisが無い可能性のある無効な呼び出しになる場合があります。PHP 5.6からエラー(非推奨)となります。

任意精度演算が簡単

PHPの整数はプラットフォーム依存で符号付き32ビット/64ビット整数、浮動小数点は倍精度のみをサポートしていました。GMP/BC Mathなど任意精度の演算をサポートするモジュールもありましたが、デフォルトの算術演算子(+ – / * など)と比較演算子(< > <= >= など)が利用出来ませんでした。PHP 5.6からはGMPで生成した任意精度の変数はオブジェクトとして扱われ、オペレーターオーバーローディングで普通の数値と同じように扱えるようになります。

$a = gmp_init(42);
$b = gmp_init(17);

var_dump($a + $b);
var_dump($a + 17);
var_dump(42 + $b);

// Outputs the following 3 times:

object(GMP)#%d (1) {
  ["num"]=>
  string(2) "59"
}

Rubyは任意精度演算が簡単に出来ます。PHPもかなり簡単にできるようになりました。以前はこんな感じでした!

$result = gmp_mod(
    gmp_add(
        gmp_mul($c0, gmp_mul($ms0, gmp_invert($ms0, $n0))),
        gmp_add(
            gmp_mul($c1, gmp_mul($ms1, gmp_invert($ms1, $n1))),
            gmp_mul($c2, gmp_mul($ms2, gmp_invert($ms2, $n2)))
        )
    ),
    gmp_mul($n0, gmp_mul($n1, $n2))
);

 

PHPDBG

もう直ぐVoteになりそうな物はPHPデバッガーです。PHP SAPIとして実装されたphpdbgは別次元のデバックとPHPアプリケーションのテストを可能にします。PHPのSAPI(Webサーバーなどが利用するサーバーAPI)として実装されているのでプログラムの実行前からデバッガーが動作します。コンパイルの状態を確認したり、実行前にクラス定義も参照できます。

The mocking of any web request just requires that you set the super globals of the script accordingly

とphpdbgサイトに書いてあるとおり、サーバーの動作、つまりPHPのWebアプリの動作を$_GET, $_POST, $_COOKIEなどの変数を設定するだけでモックできます!この機能はWebアプリのテストをかなり容易にします。追加されたらPROVE for PHPのログを、phpdbgのWebサーバーのリクエストとして利用し実行できるようにインテグレーションする予定です。

WebサーバーのSAPIの場合、CasperJSやPhantomJS、PHPのcURLなどでテストする必要があります。CGI SAPIを使えばPHP単体でテスト可能でしたが、Webブラウザの出力と同じ入力にしなければならならず容易ではありませんでした。

phpdbgではPHPのみで簡単にサーバー側アプリのテストが可能になります。どちらがシンプルで分り易く、問題が起きた場合の原因を分離しやすいか、言うまでもありません。Webサーバーで実行することなくWebアプリのテストが行えるようになることはテストマニアには堪らない機能になります。

PHPのソースディストーションに入れる事に異論を持っている開発者も居るのでまだどうなるかは分かりませんが、私はphpdbgをPHPソースへ追加することに賛成します。日本人でPHPのVote権を持っている人で投票しているのは最近は私くらいです。Vote権を持っている方、ぜひVote権を使ってphpdbgの追加に賛成をお願いします!

個人的に提案したい変更

手前味噌ですがSessionモジュールのAPI拡張(速くなる)、default_charsetのデフォルト値の設定(UTF-8)、値の利用(default_charsetを設定するだけでmbstring.insternal_encodingなどが同じ値に)を提案しようと思っています。ただ、時間が無いので間に合うかは微妙です。

追記:

sessionモジュールの高速化は間に合いませんでしたが、文字エンコーディングのデフォルト設定を全てUTF-8にし、PHP全体のデフォルト設定として利用できるINI設定の追加は行われました。

 

PHP Advent Calender 2013、明日はesehara@githubさんです。

投稿者: yohgaki