PHP7.3.0α1の新機能

[PHP7.3.0](https://qiita.com/rana_kualu/items/48e6e4baaeb265ab9fa7) / [PHP7.3.0α1](https://qiita.com/rana_kualu/items/a7c6be77e165bca0f3fc) / [PHP7.2](https://qiita.com/rana_kualu/items/40ebed78742bfdbd1065) / [PHP7.1](https://qiita.com/rana_kualu/items/f8baf30752928346bef8)



2018/06/07に[PHP7.3.0 alpha1](http://php.net/archive/2018.php#id2018-06-07-1)がリリースされました。
[リリースノート](https://github.com/php/php-src/blob/php-7.3.0alpha1/NEWS)はいつものように`Fixed bug`で埋まってますが、幾つか[RFC](https://wiki.php.net/rfc#php_73)で決定した新機能が取り込まれてるので見てみます。

# RFC

## [Flexible Heredoc and Nowdoc Syntaxes](https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes)

[ヒアドキュメント](http://php.net/manual/ja/language.types.string.php#language.types.string.syntax.heredoc)と[nowdoc](http://php.net/manual/ja/language.types.string.php#language.types.string.syntax.nowdoc)が微妙に使いづらかったのが改善されます。

```php
class foo {
    public $bar = <<<EOT
bar
EOT;
}
```

終端IDは必ず行頭に置き、空白を入れてはいけない、終端ID以外の文字を置いてもいけない、ということになっています。
クラスやメソッド中などに出てくると、その部分だけインデントがなくなって残念な見た目になります。

```php

// これまでの形式
echo <<<END
      a
     b
    c
END;
/*
      a
     b
    c
*/

// 追加の記法
echo <<<END
      a
     b
    c
    END;
/*
  a
 b
c
*/

```

上記例では、スペース4個の後に終端IDを書いています。
この場合、ヒアドキュメント文字列も、各行の行頭スペース4個が削除された状態の文字列になります。
自然に書くだけで思ったような文字列が書けるようになるので、これまでよりずっと使いやすくなりそうです。

また、インデントにはスペース以外にタブも使えます。

```php

// 文字列のインデントが足りないとParseError
echo <<<END
  a
 b
c
 END;

// インデントにタブとスペースを混ぜるとParseError
{
	echo <<<END
		  a
		 END;
}
```

さらに何故か終端IDの改行要件も削除されます。
正直こちらは入れなくてもよかったんじゃないかという気がしてならないのですが、賛成26反対8の圧倒的多数で可決されました。

```php
// 動く
$values = [<<<END
a
b
ENDING
END, 'd e f'];

// ParseError
$values = [<<<END
a
b
END ING
END, 'd e f'];

// ParseError
echo <<<END
END{$var}
END;
```

終端IDと同じ文字列がヒアドキュメント文字列中にあると、場合によってはパースエラーになります。
ここは明らかに互換性がなく、英文をヒアドキュメントにしているとひっかかるかもしれません。
ほとんど無いとは思いますが、ヒアドキュメントを多用している場合はバージョンアップに注意しましょう。


## [Allow a trailing comma in function calls](https://wiki.php.net/rfc/trailing-comma-function-calls)

関数呼び出しで末尾カンマが使えるようになります。

末尾カンマというのは

```php
	use Foo\Bar\{
	    Foo,
	    Bar,
	};
	
	$array = [1, 2, ];
```

最後の`,`のことで、これまでも配列などで使うことができました。
今後は関数とメソッド、および関数っぽいものの呼び出しにも使えるようになります。

```php
	sprintf($format, $arg1, $arg2, );
	var_dump($a, $b, );
	isset($c, $d, );
	
	$datetime->format('Y-m-d', );
```

これができて何がうれしいかというと、可変長引数の関数にコピペで引数追加したいときですね。
`var_dump()`の末尾,にひっかかったことのある人も多いはず。

```php
	// ParseError 2個は駄目
	foo('function', 'bar',,);
	
	// ParseError 途中省略は不可
	foo('function', , 'bar');
```

個人的には[途中省略](https://qiita.com/rana_kualu/items/180990033bd9b1b2c316#skipping-optional-parameters)がほしいのですが。


## [JSON_THROW_ON_ERROR](https://wiki.php.net/rfc/json_throw_on_error)

`json_encode()`や`json_decode()`は処理に失敗したかどうかがわかりにくいです。
[json_decode](http://www.php.net/json_decode)は失敗時にnullを返しますが、`json_decode(null)`もnullになるので区別がつきません。
nullになるたびに[json_last_error](http://php.net/manual/ja/function.json-last-error.php)で調べなければならないという状態です。

そこで定数JSON_THROW_ON_ERRORを追加します。
json_encode/decodeがエラーになるとJsonExceptionが発生するようになります。

```php
	try{
		json_decode($invalidJson, true, 512, JSON_THROW_ON_ERROR);
	}catch(JsonException $e){
		echo 'JSONデコードでなんかエラー' . json_last_error_msg();
	}
```

ここエラーメッセージは`$e`から取るべきなのだろうけど、その場合`json_last_error_msg`の中身はどうなるんだろう？
そもそも`json_decode`のオプションが第4引数ってのはどうにかならんのですかね。


## [PCRE2 Migration](https://wiki.php.net/rfc/pcre2-migration)

現在のPHPに入っている正規表現ライブラリ[PCRE](http://php.net/manual/ja/pcre.installation.php)はバージョン8.xですが、これを[PCRE2](http://pcre.org/current/doc/html/index.html)に移行します。
PCREとどう違うのかはよくわかりません。
既存のテストでは[bug75207](https://github.com/php/php-src/blob/master/ext/pcre/tests/bug75207.phpt)だけがPCRE2の影響を受けたようです。


## [list() Reference Assignment](https://wiki.php.net/rfc/list_reference_assignment)

`list()`で[リファレンス渡し](http://php.net/manual/ja/language.references.pass.php)が使えるようになります。

```php
	// 7.2まではFatal error
	$array = [1, 2];
	list($a, &$b) = $array;
```

おいやめろ馬鹿。この機能は早くも終了ですね。
こんなもの実装するとかちょとsYレならんしょこれは･･･？


## [is_countable function](https://wiki.php.net/rfc/is-countable)

PHP7.2で[count()](https://qiita.com/rana_kualu/items/40ebed78742bfdbd1065#counting-of-non-countable-objects)にE_WARNINGが発生するようになったことに伴い、countできるかどうかの判定が必要になりました。

```php
if (is_array($foo) || $foo instanceof Countable) {
    // $foo is countable
}
```

面倒なので標準関数を用意しました。

```php
if (is_countable($foo)) {
    // $foo is countable
}
```

そこまでしなくてもという気もしますが、なんというかPHPらしい関数ですね。


# その他

PHP7.3で取り込まれたRFCは以上ですが、RFCには載ってないような小さな改修も多々あります。

## No way to get current scale in use

[bcscale](http://php.net/manual/ja/function.bcscale.php)はスケール値を設定しますが、現在設定されているスケール値を[取得する方法がありません](https://bugs.php.net/bug.php?id=67855)。
そこで引数がない場合は現在のスケール値を返すようになります。

## Add DateTime::createFromImmutable() method

DateTimeからDateTimeImmutableを作る[DateTimeImmutable::createFromMutable](http://php.net/manual/ja/datetimeimmutable.createfrommutable.php)というメソッドがあるのですが、それの対となるDateTime::createFromImmutableが追加されます。
そもそもどちらにしろ誰が使うのかわかりませんが。

## Added support for WebP in imagecreatefromstring()

[imagecreatefromstring](http://php.net/manual/ja/function.imagecreatefromstring.php)関数がWebP形式に対応しました。
Image関数は多すぎるのでもうちょっと整理してほしいですね。

## Add net_get_interfaces()

[net_get_interfaces](https://github.com/php/php-src/pull/2935/files)関数が追加されました。
ネットワークインターフェイスを取得する関数で、IPアドレスにネットマスク、MACアドレスなどを取得できるみたいです。
`ifconfig`みたいなものでしょうか。

## Added gmp_** function

[gmp_binomial](https://ja.wikipedia.org/wiki/%E4%BA%8C%E9%A0%85%E5%88%86%E5%B8%83)、[gmp_lcm](https://ja.wikipedia.org/wiki/%E6%9C%80%E5%B0%8F%E5%85%AC%E5%80%8D%E6%95%B0)、[gmp_perfect_power](https://ja.wikipedia.org/wiki/%E7%B4%AF%E4%B9%97%E6%95%B0)、[gmp_kronecker](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%8D%E3%83%83%E3%82%AB%E3%83%BC%E7%A9%8D)の各関数が追加されました。
今のところ詳細が[ソース](https://github.com/php/php-src/blob/master/ext/gmp/gmp.c)にしかないので詳細はわかりませんが、おそらくはまあ名前どおりでしょう。
それにしても名前かっこいいなパーフェクトパワー。

## Added openssl_pkey_derive function

[openssl_pkey_derive](https://github.com/php/php-src/pull/3197)関数が追加されました。
公開鍵暗号の共有鍵を生成する関数で、単にOpenSSLの[EVP_PKEY_derive](https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_derive.html)関数を呼んでいるだけのようです。
わざわざPHPでやる必要もない気はしますが。

## Removed support for BeOS / ODBCRouter / Birdstep

マジか！これは許されざる変更！！

ところでBeOSでPHPを使ってた人ってどれだけ居るんですかね。
そもそもBeOSが使われているところ自体見たことないですけどね。


# 感想

ヒアドキュメントと末尾カンマがいいかんじですが、listリファレンスがそれらを補って余りあるマイナスだ。
使うなよ！絶対に使うなよ！

本リリースは名前のとおりまだα版で、本番環境で利用するものではありません。
今後もまたバグを潰していって完成度が高まったところでリリース版が出るでしょうから、遊びで使う人以外はそれまで待ちましょう。
7.2からの互換性が壊れるところはほぼないので、リリースされたらさくっとバージョンアップしてもよさそうです。