PHP
エイプリルフール

PHP6.0移行ガイド

More than 1 year has passed since last update.

リリースノート

2016年4月1日に,PHP6.0がリリースされました.

PHP 6 Changelog

新機能

PHP5.6からPHP7.0への大規模なアップデートが話題になりましたが,更にPHP7.0からPHP6.0に向けて後方互換性に関わる数多くの変更が行われています.

内部文字コードUTF-16化

PHP6.0から,JavaやC#のように,処理系内部において文字列が全て文字コードUTF-16で保持されるようになります.これにより,そのままでは挙動に変化はありませんが,declare宣言にてencodingを明示したときに違いが表れます.

指定なし
<?php
$str = '本当だよ';
echo substr($str, 0, 6); // 本当
echo mb_substr($str, 0, 2); // 本当
指定あり
<?php
declare(encoding='UTF-8');
$str = '嘘じゃないよ';
echo substr($str, 0, 1); // 嘘
echo $str[0]; // 嘘

このように,従来はmbstring拡張の関数を利用して書いていたところが,通常の関数を用いて処理できるようになります.それに伴い,mbstring拡張がPHP6.0からはDeprecatedになることも決定されました.

上記の例ではUTF-8を用いましたが,今後はShift_JISで使われることが増えていくと予想されます.実際この変更が導入された背景にはBash on Windowsの発表があり,「文字コードShift_JISで出来るだけ快適にPHPコードを書きたい」という声も既に上がっています.

演算子の挙動変更

古くからPHPは文字列連結にはドット演算子.,オブジェクトメンバの参照にはアロー演算子->,連想配列の定義にはダブルアロー演算子=>を用いていましたが,ポピュラーな他の言語との互換性を考慮して,PHP6.0からは以下のように変更されます.

文字列連結はプラス演算子が行う
$s = 'a' + 'b';
echo $s; // ab
メンバ参照はドット演算子が行う
$rows = $pdo.query('SELECT * ...').fetchAll(PDO::FETCH_ASSOC);
連想配列の定義はコロン演算子が行う
$assoc = [
    'a': 'b',
    'c': 'd',
];

なお,連想配列のキーのクオーテーションは省略することが可能です.

$assoc = [
    a: 'b',
    c: 'd',
];

Scalar Objects

スカラー値からメソッドが生やせるようになる nikic/scalar_objects 拡張が注目を集めていましたが,PHP6.0からはこれが標準で導入されます.基本的なメソッドも定義されています.

$r = [1, 2, 3, 4].map(function ($x) { return $x + 1; })
                 .map(function ($x) { return $x * 2; })
                 .join(',');
echo $r; // 4,6,8,10

Short Closure

Scalar Objects の採用に伴い,より短いシンタックスを実現するために,クロージャの短縮記法が導入されました.役割を失った->はこちらで活用されます.

$r = [1, 2, 3, 4].map($x -> $x + 1)
                 .map($x -> $x * 2)
                 .join(',');
echo $r; // 4,6,8,10

また「変数をuseでインポートするのが煩わしい」との声に答え,クロージャを生成したスコープに存在する変数を暗黙的にインポートする記法も用意されました.こちらでは=>を用います.

$y = 'World';
echo ($x => "$x, $y")('Hello'); // Hello, World

Implicit Variable

PHPは歴史的な理由で,Noticeを発生しながらも未定義の定数を文字列として扱っていましたが,PHP6.0からは以下のように挙動が変更されます.

  • 文字列ではなく変数名として扱われるようになる
  • Noticeが発生しなくなる

よってPHP6.0からは以下のようなコーディングスタイルが推奨されます.

r = [1, 2, 3, 4].map(x -> x + 1)
                .map(x -> x * 2)
                .join(',');
echo r; // 4,6,8,10

Named Closure

以前のPHPでも,mpyw/phpext-calleeのようなエクステンションを作れば,クロージャを無名再帰させることが可能でした.

<?php
var_dump((function ($n) {
    return $n < 2 ? 1 : $n * callee()($n - 1);
})(5));

// 5! = 5 * 4 * 3 * 2 * 1 = int(120)

PHP6.0からはJavaScriptのように,クロージャに再帰用の名前が付けられるようになります.

<?php
var_dump((function self($n) {
    return $n < 2 ? 1 : $n * self($n - 1);
})(5));

// 5! = 5 * 4 * 3 * 2 * 1 = int(120)