これはWhat PHP 5.5 might look likeの翻訳です。誤訳などあればコメントくださいm(_ _)m
PHP5.4が4ヶ月前にリリースされました。なので、次のPHPのバージョンを見るのはちょっと早すぎるかもしれません。ですが、Internalsメーリングリストをフォローしていないすべての方に、PHP5.5がどのようになるかについて紹介したいと思います。
ただし、この点は理解して下さい: PHP5.5は初期開発の段階にあります。なので、誰も最終結果がどのようになるか知りません。私がここで話すものはすべて 提案(proposal) のものについてです。以下に挙げるすべてのものがPHP5.5に盛り込まれるとは限りません。
ですので、これについてあまり盛り上がりすぎないでください :)
この新機能/提案のリストは大きく、重要度順ではありません。なので、すべてを読みたくない人には、ここに4つの機能をあげておきます。私が個人的に面白いと思った機能です。
- パスワードハッシュ化のためのシンプルなAPI
- スカラータイプヒンティング
- ゲッターとセッター
- ジェネレーター
では、前置きはこれくらいにして、PHP5.5で取り組まれているもののリストを見てみましょう。
非上位互換
まず、既にmasterに取り込まれている2つの非上位互換の変更からはじめましょう。
Windows XP と 2003 のサポート終了
Status: landed; Responsible: Pierre Joye
PHP 5.5 はこれ以上Windows XPと2003をサポートしません。これらのシステムは10年ほど前のものです。なので、PHPはそれらの対応を終了します。
/e
修飾子が非推奨になる
Status: landed; Responsible: myself
e
修飾子は preg_replace
関数に対し、単純な置換をする代わりに、置換文字列をPHPコードとして評価するよう命令するものです。予想できると思いますが、この挙動は問題が絶えず、セキュリティ的にも問題があります。これが、PHP5.5でこの修飾子を使うと非推奨警告を投げるようになる理由です。代替手段としては preg_replace_callback
関数を使うといいでしょう。この変更についてもっと知りたい場合はこちらのRFCを御覧ください。
関数とクラスの追加
次に追加予定の関数とクラスを見てみましょう。
boolval()
Status: landed; Responsible: Jille Timmermans
PHPはすでに strval
, intval
そして floatval
関数を実装しています。首尾一貫するために、 boolval
関数が新たに追加されます。この関数自体は (bool)
でキャストするのと同じものですが、コールバック関数で使えるようになります。
hash_pbkdf2()
Status: landed; Responsible: Anthony Ferrara
PBKDF2はPassword-Based Key Derivation Function 2の略で、名前が語っているように、パスワードから暗号化キーを取得するためのアルゴリズムです。これは暗号化アルゴリズムに必要ですが、パスワードのハッシュ化にも使うことができます。詳しい説明と使い方についてはRFCを御覧ください。
国際化関数(intl)の追加
Status: landed; Responsible: Gustavo André dos Santos Lopes
intl拡張には多くの改良があります。例えば、新たに IntlCalendar
, IntlGregorianCalendar
, IntlTimeZone
, IntlBreakIterator
, IntlRuleBasedBreakIterator
, IntlCodePointBreakIterator
クラスが追加されます。残念ながら私はintl拡張についてよく知りませんので、メーリングリスト上のCalendarとBreakIteratorのアナウンスへのリンクを紹介する程度にしておきます。興味があれば御覧ください。
array_column()
Status: proposed; Responsible: Ben Ramsey
これは array_column
(または array_pluck
) 関数についての提案です。この関数は次のような動作をします。
<?php
$userNames = array_column($users, 'name');
// は次と同じ
$userNames = [];
foreach ($users as $user) {
$userNames[] = $user['name'];
}
これはデータベースからカラムを取得するような感じでしょうが、配列に対して使うものです。
パスワードハッシュ化のためのシンプルなAPI
Status: proposed; Responsible: Anthony Ferrara
最近のパスワード漏洩事件(LinkedInなど)は、大きなウェブサイトでさえ適切にパスワードをハッシュ化する方法を知らないということを示しています。中には数年前から bcrypt を使うべきと主張する人がいましたが、まだ多くの人が完全に安全でない sha1
ハッシュを使っています。
私たちは、この原因に crypt
関数のAPIの使いにくさがあるのだろうと気づきました。そこで、私たちは安全なパスワードハッシュのための新しくシンプルなAPIを紹介したいと思います。
<?php
$password = "foo";
// ハッシュを作る
$hash = password_hash($password, PASSWORD_BCRYPT);
// パスワードをチェックする
if (password_verify($password, $hash)) {
// 正しいパスワード
} else {
// 間違っているパスワード
}
この新しいハッシュAPIは他にもいくつかの機能がついています。詳細は RFC にアウトラインがあります。
言語仕様の変更
実に興味深い項目にやってきました。言語の新仕様と強化についてです。
コンスタント・デリファレンス(Constant dereferencing)
Status: landed; Responsible: Xinchen Hui
「コンスタント・デリファレンス」は文字列や配列リテラルに対して、直接的に配列操作できるというものです。ここに2つの例があります。
<?php
function randomHexString($length) {
$str = '';
for ($i = 0; $i < $length; ++$i) {
$str .= "0123456789abcdef"[mt_rand(0, 15)]; // 文字列のダイレクトデリファレンス
}
}
function randomBool() {
return [false, true][mt_rand(0, 1)]; // 配列のダイレクトデリファレンス
}
私はこの機能が実際にたくさん使われるとは思いませんが、これが言語仕様をより首尾一貫したものにすると思います。これについてもRFCを参照してください。
empty()が関数コールで動くようになる
Status: landed; Responsible: myself
現在、empty()
言語構造は変数に対してのみ使用可能です。他の表現には使用できません。たとえば empty($this->getFriends())
のようなコードはエラーが投げられます。PHP5.5ではこれは正しいコードになります。詳細はRFCを御覧ください。
クラスの完全名を取得する
Status: proposed; Responsible: Ralph Schindler
PHP5.3では、クラスにエイリアスをつけることができる機能と共にネームスペースが追加されました。しかし、このエイリアスは文字列のクラス名には適用できません。
<?php
use Some\Deeply\Nested\Namespace\FooBar;
// これはグローバルの FooBar クラスを使おうとするので、動きません。
$reflection = new ReflectionClass('FooBar');
これを解決するために、新しく FooBar::class
シンタクスが提案されています。これは、クラスの完全名を返すものです。
<?php
use Some\Deeply\Nested\Namespace\FooBar;
// FooBar::classは "Some\\Deeply\\Nested\\Namespace\\FooBar" と解釈されるので動きます。
$reflection = new ReflectionClass(FooBar::class);
詳しい例についてはRFCを御覧ください。
パラメータスキップ
Status: proposed; Responsible: Stas Malyshev
現在は、複数の任意引数を受け取る関数で、最後のひとつだけを変更し、他の引数をデフォルトのままにする方法がありません。
RFCからの例を見てみましょう。下記のような関数で、
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) { ... }
他の2つのデフォルト値をコピーせずに $report_errors = false
をセットする方法がありません。これを解決するために、パラメータスキップの方法が提案されています。
create_query("deleted=0", "name", default, default, false);
個人的にこの提案はあまり好きではありません。この機能が必要なコードは単に設計が悪いからだと思うからです。関数は 12個もの任意パラメータを持つべきではありません。
スカラータイプヒンティング
Status: proposed; Responsible: Anthony Ferrara
スカラータイプヒンティングは本来5.4で取り込まれる予定でした。しかし、合意が間に合わず取り込まれませんでした。なぜスカラータイプヒンティングがまだPHPに取り込まれていないか知らいたい方は Scalar typehints are harder than you think を御覧ください。
PHP 5.5では討論が再度行われました。キャスト付きスカラータイプヒンティングの提案がだいぶいいのではないかと思います。
これは入力値を特定の型にキャストするものですが、データのロスなしでキャストできる場合に限ります。例えば 123
, 123.0
, "123"
は int
パラメータの入力値として正しいということになりますが、 "hallo world"
は正しくない入力値になります。これは、内部関数の挙動と同じです。
function foo(int $i) { ... }
foo(1); // $i = 1
foo(1.0); // $i = 1
foo("1"); // $i = 1
foo("1abc"); // not yet clear, maybe $i = 1 with notice
foo(1.5); // not yet clear, maybe $i = 1 with notice
foo([]); // error
foo("abc"); // error
ゲッターとセッター
Status: proposed; Responsible: Clint Priest
もしあなたが getXYZ()
や setXYZ($value)
のようなメソッドをいちいち書くことが面倒だと感じているのであれば、この変更はあなたにとって歓迎すべきものでしょう。この提案は、プロパティがセット/ゲットされたときに、何が起こるかを定義するためのシンタクスを追加します。
<?php
class TimePeriod {
public $seconds;
public $hours {
get { return $this->seconds / 3600; }
set { $this->seconds = $value * 3600; }
}
}
$timePeriod = new TimePeriod;
$timePeriod->hours = 10;
var_dump($timePeriod->seconds); // int(36000)
var_dump($timePeriod->hours); // int(10)
他にも read-only プロパティのような機能もあります。より詳しく知りたければRFCを御覧ください。
ジェネレーター
Status: proposed; Responsible: myself
現在、カスタムイテレータはあまり使われません。実装が多くのひな形コードを必要とするためです。ジェネレーターは、イテレータを作るためにひな形コードいらずの簡単な方法を提供してこの問題を解決します。
たとえば、これはイテレータとして range
関数がどのように定義できるかの例です。
<?php
function *xrange($start, $end, $step = 1) {
for ($i = $start; $i < $end; $i += $step) {
yield $i;
}
}
foreach (xrange(10, 20) as $i) {
// ...
}
上の xrange
関数はビルトイン関数の range
と同じ動きをしますが、ひとつの違いがあります。すべての値を含んだ配列を返す代わりに、値をその都度生成するイテレータを返します。
より深い紹介についてはRFCのトピックを御覧ください。
リスト内包表記とジェネレーター表現
Status: proposed; Responsible: myself
リスト内包表記は小さな配列操作に簡単な方法を提供します。
$firstNames = [foreach ($users as $user) yield $user->firstName];
上のリスト内包表記は次のコードと等価です。
$firstNames = [];
foreach ($users as $user) {
$firstNames[] = $user->firstName;
}
また、次の方法で配列をフィルタすることもできます。
$underageUsers = [foreach ($users as $user) if ($user->age < 18) yield $user];
ジェネレーター表現と似ていますが、配列を返す代わりにイテレータを返します。
もっと例をご覧になる場合はメーリングリストのアナウンスを御覧ください。
まとめ
ご覧のとおり、PHP5.5のための素晴らしい提案が沢山あります。しかし、上で言ったとおり、PHP5.5はまだ初期段階です。なので、どれが採用され、どれが採用されないかはまだわかりません。
新機能について最新情報を受け取りたい、ディスカッションや開発を手伝いたいという方は、internalsメーリングリストを購読してみてください。