PHP 7 リリース内容の確認


遅くなりましたが Advent Calendar 1 日目を担当させて頂く @ken880guchi です。
いよいよ、明後日 12/3 (書いている日付けだと明日)に PHP 7 がリリースされそうですね！

本日は、そんな PHP 7 のリリース内容について、[PHP 7.0.0 RC 8 Released](http://php.net/archive/2015.php#id2015-11-26-1) 内の下記の記述に沿って確認していきたいと思います。

- Improved performance
- Consistent 64-bit support
- Many fatal errors are now Exceptions
- Removal of old and unsupported SAPIs and extensions
- The null coalescing operator (??)
- Combined comparison Operator (<=>)
- Scalar Type Declarations
- Return Type Declarations
- Anonymous Classes
 

## Improved performance と Consistent 64-bit support

[PHP RFC: 64 bit platform improvements for string length and integer in zval](https://wiki.php.net/rfc/size_t_and_int64_next)

PHP 7 では PHP 5 系に比べて 2 倍の処理速度を実現しているそうです。
どのように実現しているのか Consistent 64-bit support の項と合わせて確認していましたがよく解らずで、実際にパフォーマンスを測定するためのプログラムを書いて確認してみました。


```php
<?php
$time_start = microtime(true);

$tmp = 0;
for ($i = 0; $i < 10000000; $i++) {
  $tmp++;
}

$time_end = microtime(true);
$time = $time_end - $time_start;
var_dump($time);

//php 5.4
float(0.42663598060608)
float(0.39912509918213)
float(0.38065600395203)
float(0.38405990600586)
float(0.37619996070862)

//php 7
float(0.18235611915588)
float(0.16087293624878)
float(0.16647410392761)
float(0.1587450504303)
float(0.15866303443909)
```

確かに早い...!! すごいぞ PHP 7 !!

あと、気になったのですが連続で実行していると処理時間がぐんぐん縮まっているのは PHP の Cache とかの仕組みなのでしょうか？この辺も引き続き調べて行けたらなと思います。

## Many fatal errors are now Exceptions

[PHP RFC: Exceptions in the engine (for PHP 7)](https://wiki.php.net/rfc/engine_exceptions_for_php7)

PHP 7 では多くの致命的なエラーを例外としてキャッチできるようになっているようです。具体的に自身で検証する時間が無かった為、どのようなエラーがキャッチできるようになっているかが把握出来ていませんので、後日、改めて別の投稿にて追加したいと思います。

## Removal of old and unsupported SAPIs and extensions

[PHP RFC: Removal of dead or not yet PHP7 ported SAPIs and extensions](https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts)

古い。またはサポートされていない幾つかの SAPI が削除されたようです。そもそも、SAPI とは何かということを知らなかった自分が調べてみると Server-API の略ということが解りました。PHP においては PHP を支える Zend エンジンを外部から利用する為の API の役割になるもののようです。PHP の拡張を実装される方々には有名なのかもしれません。

削除された SAPI の一覧

- aolserver
- apache
- apache_hooks
- caudium
- continuity
- isapi
- milter
- phttpd
- pi3web
- roxen
- thttpd
- tux
- webjames
- apache2filter - not really dead, but currently broken
- nsapi

## The null coalescing operator (??)

[PHP RFC: Null Coalesce Operator](https://wiki.php.net/rfc/isset_ternary)

新しい演算子 ?? が追加されました。変数に値が設定されている場合(null を除く) は ?? の左辺の値を、null の場合や存在しない場合は ?? の右辺に記述された値を代入します。個人的に PHP 7 に乗り換えた場合に、この演算子の使用頻度は非常に高くなると思います。具体的に自身が使用したいと思うような処理は、下記のような初期化の処理になります。

```php 
// 今まで
$name = isset($arr['name']) ? $arr['name'] : '';
// php 7
$name = $arr['name'] ?? '';
```

## Combined comparison Operator (<=>）

[PHP RFC: Combined Comparison (Spaceship) Operator](https://wiki.php.net/rfc/combined-comparison-operator)

新しい演算子 <=> が追加されました。RFC にある下記のサンプルで挙動を確認してみました。Object は値での比較しか出来ないようです。また、RFC 内の Usefulness という項目で使用用途を確認してみたところ、主に並び替えの関数に使用するようでした。自分としては使い道が良く解っていません。

```php
<?php
// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
 
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
 
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
 
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
 
// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
 
// Objects
$a = (object) ["a" => "b"]; 
$b = (object) ["a" => "b"]; 
echo $a <=> $b; // 0
 
$a = (object) ["a" => "b"]; 
$b = (object) ["a" => "c"]; 
echo $a <=> $b; // -1
 
$a = (object) ["a" => "c"]; 
$b = (object) ["a" => "b"]; 
echo $a <=> $b; // 1
```

## Scalar Type Declarations

[PHP RFC: Scalar Type Declarations](https://wiki.php.net/rfc/scalar_type_hints_v5) 
 
初めに、この話しを聞いた時、自分の中では下記のように変数に型を定義出来るようになったのかと勘違いしていました。下記のようにエラーとなります。

```php
<?php

int $num = 3;

var_dump($num);
```

```sh
$ php test.php

Parse error: syntax error, unexpected '$num' (T_VARIABLE) in /home/vagrant/scala.php on line 3
```

正しくは [PHP RFC: Scalar Type Declarations](https://wiki.php.net/rfc/scalar_type_hints_v5) で話されているように、引数の型を宣言出来るようになったということでした。宣言できる型は下記の 6 つになります。

- array
- callable
- bool
- float	
- int
- string

早速使ってみます。

```php
<?php

# 引数の型は int
function test(int $num) {
  return $num;
}

var_dump(test(3));
var_dump(test(3.0));
var_dump(test("3"));
var_dump(test("a"));
```

```sh
$ php scala.php

# 引数 3 の場合は 3
int(3)

# 引数 3.0 の場合は 3
int(3)

# 引数 "3" の場合は 3
int(3)

# 引数 "a" の場合はエラー
Fatal error: Uncaught TypeException: Argument 1 passed to test() must be of the type integer, string given, called in /home/vagrant/scala.php on line 10 and defined in /home/vagrant/scala.php:3
Stack trace:
#0 /home/vagrant/scala.php(10): test('a')
#1 {main}
  thrown in /home/vagrant/scala.php on line 3
```

上記だと、微妙な結果になってしまいましたが、 `declare(strict_types=1);` を先頭につけることで厳格な型チェックを行ってくれるということなので、この問題を回避出来るようです。もう一度実行。


```sh
$ php scala.php

# 引数 3 の場合は 3
int(3)

# 引数 3.0 の場合はエラー
Fatal error: Uncaught TypeException: Argument 1 passed to test() must be of the type integer, float given, called in /home/vagrant/scala.php on line 8 and defined in /home/vagrant/scala.php:3
Stack trace:
#0 /home/vagrant/scala.php(8): test(3)
#1 {main}
  thrown in /home/vagrant/scala.php on line 3
```

この後、数字の 3 と文字の a も試してみましたが同様にエラーとなり期待していた挙動を確認することが出来ました。引数に型を宣言することを徹底することで品質の向上や IDE の恩恵を最大限に受けることが出来るようなので PHP 7 からは徹底していきたいと思います。

## Return Type Declarations

[PHP RFC: Scalar Type Declarations](https://wiki.php.net/rfc/scalar_type_hints_v5) 
 
上記、その 7 で紹介した [PHP RFC: Scalar Type Declarations](https://wiki.php.net/rfc/scalar_type_hints_v5) に目を通して頂いていると既に解ってしまった方もいると思いますが、関数の返り値の型も指定することが出来るようになっています。具体的には下記のようになります。

```php
<?php
declare(strict_types=1);

# 引数の型は int. 返り値の型は array
function test(int $num) :array {
  return $num;
}

test(3);
```

上記のコードを実行すると、返り値の型を array と決定しているにも関わらず int を返す作りになっているため、下記のようなエラーメッセージが表示されます。この機能についても PHP 7 でコードを書く際は積極的に使用していきたいと思います。

```sh
$ php scala.php

Fatal error: Uncaught TypeException: Return value of test() must be of the type array, integer returned in /home/vagrant/scala.php on line 5 in /home/vagrant/scala.php:5
Stack trace:
#0 /home/vagrant/scala.php(8): test(3)
#1 {main}
  thrown in /home/vagrant/scala.php on line 5
```

## Anonymous Classes

[PHP RFC: Anonymous Classes](https://wiki.php.net/rfc/anonymous_classes) 

匿名(無名とも呼ばれている)クラスというものが新たに追加され、動的にクラスを生成できるようになります。使用用途としては [PHP RFC: Anonymous Classes](https://wiki.php.net/rfc/anonymous_classes) の Use Cases を読む限りでは主にテストコード(インターフェース用のモック作成等)に用いることが考えられているようです。また、既存のクラスとの機能差は無く、具体的な記述方法は下記のように書くことが出来ます。

```php
<?php
$day = 1;
$AnonymousClass = (new class($day) {

    public $publicProperty = '';

    private $privateProperty = '';

    public function __construct($day) {
        $this->privateProperty = "AdventCalendar {$day} 日目";
    }

    public function test() {
        echo $this->privateProperty;
    }
});

var_dump($AnonymousClass);
$AnonymousClass->test();
```

```sh
$ php test.php

# var_dump() の結果
object(class@anonymous)#1 (2) {
  ["publicProperty"]=>
  string(0) ""
  ["/home/vagrant/tryAnonymousClass.php0x7f8e73436135":"class@anonymous":private]=>
  string(23) "AdventCalendar 1 日目"
}

# $AnonymousClass->test(); の結果
AdventCalendar 1 日
```

## おわり

簡単にですがリリースノートの内容確認を行いました。現状自身にとって使わないであろう機能も有りましたが、やはり 5 系に比べて 2 倍早くなるということだけでもかなりの魅力なので、プロダクトで利用出来るように引き続き使用して行きたいと思います。

それでは、[PHP The Anthem](https://www.youtube.com/watch?v=S8zhmiS-1kw) を聞きながら 12/1 の Advent Calendar を終わらせて頂こうと思います。

![Kobito.78Khiv.png](https://qiita-image-store.s3.amazonaws.com/0/42939/173e02b2-bda6-a715-6e9b-cec697973f7d.png "Kobito.78Khiv.png")



## おまけ 1: 今直ぐ PHP 7 を試す

PHP 7 を今直ぐ試してみたい方は、PHP の生みの親である Rasmus Lerdorf さんの Github リポジトリ [rlerdorf/php7dev](https://github.com/rlerdorf/php7dev) を Clone することで、今直ぐ構築することが出来ます。(Vagrant + VirtualBox 必須)

```sh
git clone https://github.com/rlerdorf/php7dev.git php7dev

cd php7dev

vagrant up && vagrant ssh

vagrant@php7dev:~$ php -v
# 少し前に clone していたので、RC8 と比べると古い結果が表示されていると思います。
PHP 7.0.0-dev (cli) (built: May 25 2015 16:34:33) (DEBUG)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v3.0.0-dev, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies
```

php 7 の正式リリースは間近ですが、未だ php 7 を触ったことがないという人は、こうして簡単に環境も構築できるので上記変更点について確認されてみては如何でしょうか！

## おまけ 2: PHP 7 へのアップデート

PHP 7 へのアップデートについて色々書いてあるような本が、今なら無料で O'Reilly にて手に入れることが出来るようです！

http://www.oreilly.com/web-platform/free/upgrading-to-php-seven.csp