こんにちは、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 アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!