Developer's Blog

ついにリリース!PHP7!

Fenrir Advent Calendar 2015

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

Copyright © 2019 Fenrir Inc. All rights reserved.