
こんにちは、Brushup 開発担当の木戸です。
「Fenrir Adevent Calender 2015」も 10 日目となりました。
今年というかまだつい先日(この記事の一週間前)ですが、PHP7 がリリースされましたね!!なんと 10 年ぶりのメジャーバージョンアップです。
私自身もグッとくるのを楽しみながら紹介したいと思います。
新機能、変更点
実は、公式マニュアルの内容がとても素晴らしくて、そちらを読めば新機能や変更点を一通り掴めます。ここではすぐ使えそうな機能だけをピックアップして紹介します。
タイプヒンティングの拡張、戻り値の型指定
タイプヒンティングにスカラ型(int や string など)が使えるようになり、戻り値の型も指定できるようになりました。
function hoge(int $num) : int
{
if ($num === 1) {
$num = 'エラー';
}
return $num;
}
$var = 1;
echo hoge($var);
これだと Fatal Error が発生します。
致命的エラーが例外に
Fatal Error のほとんどが例外に変換されたので、↑のコードも catch できます。
function hoge(int $num) : int {...省略}
$var = 1;
try {
echo hoge($var);
} catch (Error $e) { // Exception ではなく、Error が throw される
echo $e->getMessage();
}
これは、”Return value of hoge() must be of the type integer, string returned” が出力され、処理は中断されません。
Null 合体演算子「??」
is_null や isset の機会を減らせるのでかなりうれしい機能ですね!
// $_GET['name'] が null なら 'unknown' が代入 $name = $_GET['name'] ?? 'unknown'; // 連結も可能。左から順に見て 非 null 値が見つかれば代入 $name = $_GET['name'] ?? $_POST['name'] ?? 'unknown';
宇宙船演算子
左右2つの値を比較し、1(左が大きい)/0(等しい)/-1(右が大きい) を返します。コールバック付きの sort 系関数で使うとコードがスッキリ。
$array = [3,8,5,2,6];
// 昇順にソート
// 宇宙船演算子を使わない
usort($array, function($left, $right){
if ($left === $right) {
return 0;
}
return ($left < $right) ? -1 : 1;
});
// 宇宙船演算子を使う
usort($array, function($left, $right){
return $left <=> $right;
});
define で配列
昔、CSV にして explode してるソースとかありましたね…涙が出ますね…
define('LANGUAGES', [
'PHP', 'Ruby', 'Python'
]);
echo LANGUAGES[0]; // PHP
他にもまだまだありますが、これぐらいで。あれ、これみんな新機能なの?とか思っても新機能なんです。誰がなんと言おうと。
所感ですが、型縛りと致命的エラーの回避が賛否両論ありそうで、複数人開発するなら注意が必要だと思いました。あとは便利なものばかりなので積極的に使っていきたいですね。?? はかなりグッときました。
でも今回の最重要変更点は、やっぱりこれですよね。
高速化
PHP7 の噂が出た頃から話題になってましたね!もう今(5.6)でも十分速いのですが、その倍速になったとのこと。単純ですが一番嬉しい強化機能ですよね。
ではここからはコードを実行して確認してみます。以下の検証環境を用意しました。いずれも Vagrant + Virtualbox で作成し、メモリを 1GB にしています。
- Web1(以下 PHP5.6): PHP 5.6.16、CentOS 7、Apache 2.4
- Web2(以下 PHP7): Web1 と同じで、PHP は 7
- DB: MySQL 5.6.27、CentOS 7
今回は実行速度のみ計測します。ルールは以下。
- 計測方法は Xdebug の profile を使用し、ブラウザから実行して画面表示するまでの速度を見る
- OPCache 等は使わない
- 検証コードはいずれも各環境で数回実施して中央値を取る
DB にはあらかじめテストデータとして、users テーブル(id, name)とレコードを 1 万件作っておきます。
まずは単純なループ文から。
function loopTest()
{
for ($i = 0; $i < 10000; $i++) {
echo '<li>' . $i . '</li>';
}
}
(中略)
<ul>
<?= loopTest(); ?>
</ul>
PHP5.6: 10ms
PHP7: 5ms
まさに倍速の結果が得られました!ループが特に速くなったと聞いていましたが、間違いないようです。
次に、DB サーバからデータを取得してループしてみましょう。
function getUsers()
{
$dsn = 'mysql:dbname=test;host=***.***.**.**'
try {
$pdo = new PDO($dsn, 'testuser', '*********');
} catch (PDOException $e) {
echo $e->getMessage();
return;
}
$st = $pdo->query('SELECT * FROM users ORDER BY id LIMIT 100');
while($row = $st->fetch(PDO::FETCH_ASSOC)) {
echo '<li>id:' . $row['id'] . ' name:' . $row['name'] . '</li>';
}
}
(中略)
<ul>
<?= getUsers(); ?>
</ul>
PHP5.6: 18ms
PHP7: 14ms
DB からデータを取得する時間はどちらも同じなので、その分が足されただけですね。当然の結果なのですが、実行前は少し期待してました…
高速化してることは何度も検証してみてよくわかりましたが、速度は言語以外の要因の方が強いですね。ここ大事ですね。肝に命じます。
最後に
実はフレームワーク(Laravel5、Symfony3、CakePHP3)の検証もしましたが、PHP バージョンによる速度差はほぼありませんでした。それより PHP7 で動作する互換性にグッときました。PHP7 に最適化されたフレームワークが出る日がまた楽しみですね!
簡単な動作確認だけなら、PHP の原作者 Rasmus さん作の Vagrant Box もあります!みなさんも新しい PHP に触れてみてはいかがでしょうか。
フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!









