PHP7.4の新機能その2

[PHP7.4](https://qiita.com/rana_kualu/items/50f9f5735321fe995ff5) / [PHP7.4その1](https://qiita.com/rana_kualu/items/38c9917f634bc7767f1b) / [PHP7.4その2](https://qiita.com/rana_kualu/items/993fff9662726a004660)

2019/06/13、PHP7.4.0α1が[リリースされました](https://www.php.net/archive/2019.php#id2019-06-13-1)。
今後はベータ、RCと完成度を高めていき、7.4.0のリリースは[2019/11/28が予定](https://wiki.php.net/todo/php74)されています。

なお仕様フィックスは2019/07/13で、それ以降は大きな変更は入らないようになります。
逆に言うとそれまでは追加が入る可能性はあるのですが、既にα1も出たことですし、さすがにこれからのタイミングで[プロパティ型指定](https://qiita.com/rana_kualu/items/9b4502d229d19635ef34)やら[アロー関数](https://qiita.com/rana_kualu/items/7fbdd520a7e355599f7d)レベルの大改修が入ることはないでしょう。

ということで[前回](https://qiita.com/rana_kualu/items/38c9917f634bc7767f1b)以降入った新機能や変更点を見てみることにします。

# RFC

## [Arrow functions 2.0](https://wiki.php.net/rfc/arrow_functions_v2)

賛成51、反対8で受理。

[アロー関数](https://qiita.com/rana_kualu/items/7fbdd520a7e355599f7d)です。

```php
	// 新構文
	$fn = fn($x) => $x + $y;

	// ↓と同じ
	$fn = function ($x) use ($y) {
	    return $x + $y;
	};
```

`function`のもったり感から解放されます。


## [Change the precedence of the concatenation operator](https://wiki.php.net/rfc/concatenation_precedence)

賛成31、反対4で受理。

[演算子+-.の優先順位変更](https://qiita.com/rana_kualu/items/db7ae541016bd0b02122)です。

```php
	// PHP7.3まで
	echo "3" . "5" + 7; // 42
	
	// PHP7.4
	echo "3" . "5" + 7; // 42だがE_DEPRECATED
	
	// PHP8
	echo "3" . "5" + 7; // "312"
```

数値演算が文字列結合より優先されるようになり、イメージした通りの計算結果になりやすくなります。
まあ、こういうのはそもそも括弧を使うべきだとは思いますが。


## [Numeric Literal Separator](https://wiki.php.net/rfc/numeric_literal_separator)

賛成33、反対11で受理。

[数値セパレータ](https://qiita.com/rana_kualu/items/d72854f9aec6d7cf8bc6)です。

```php
$threshold = 1_000_000_000;
$testValue = ‪107_925_284.88;
$discount = 135_00;
```

数値が見やすくなります。
テストに失敗して一時期Pending行きになっていたのですが、その後無事にマージすることができたようです。


## [Deprecate left-associative ternary operator](https://wiki.php.net/rfc/ternary_associativity)

賛成35、反対10で受理。

[三項演算子のネスト制限](https://qiita.com/rana_kualu/items/0de1e406f72c0ef86432)です。

```php
1 ? 2 : 3 ? 4 : 5;   // deprecated
(1 ? 2 : 3) ? 4 : 5; // ok
1 ? 2 : (3 ? 4 : 5); // ok
```

何故か[他言語と異なる評価順](https://qiita.com/ritsuka/items/b4f78ac4121ce5e01173)の三項演算子を今後合わせていくための布石で、括弧を使わずにネストするとE_DEPRECATEDが発生するようになります。


## [Allow throwing exceptions from __toString()](https://wiki.php.net/rfc/tostring_exceptions)

賛成42、反対0で受理。

[__toString()が例外を吐ける](https://qiita.com/rana_kualu/items/5976b2b4361e6e559644)ようになります。
ユーザ側というより、エクステンション開発者向けの機能なのかもしれません。

「マージしたら[めっちゃコンフリクトした](https://github.com/php/php-src/pull/3887#issuecomment-499072192)」とかnikicが言ってました。


## [Covariant Returns and Contravariant Parameters](https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters)

賛成39、反対1で受理。

[共変戻り値と反変パラメータ](https://qiita.com/nishimura/items/0d886870044759e6d5f4)のRFC。

単語の意味はよくわかりませんが、簡単に言うと、子クラスの型宣言で親クラスの型宣言を狭められるというものです。

```php
class A {
    function test(): DateTimeInterface{
        return new DateTimeImmutable();
    }
}

class B extends A {
    function test(): DateTimeImmutable{
        return new DateTimeImmutable();
    }
}
```

PHP7.3までは`B:test`の返り値の型が`A::test`と違う、と怒られていました。
Javaあたりでは[普通にできる](http://www.ne.jp/asahi/hishidama/home/tech/java/covariant.html)ので、それを取り入れたものでしょう。
継承関係にないクラスを指定したり、逆に型宣言を広げたりすると、当然ながら今後も怒られます。


## [Spread Operator in Array Expression](https://wiki.php.net/rfc/spread_operator_for_array)

賛成43、反対1で受理。

[引数アンパック](https://qiita.com/rana_kualu/items/206d786a2be7942c6dc3#argument-unpacking-via-)を配列中でも使えるようになります。

```php
$array1 = [11, 12];
$array2 = [21, 22];
$array = [1, ...$array1, 2, ...$array2, 3]; // [1, 11, 12, 2, 21, 22, 3]
```

地味だけど、正直今回の変更点の中で一番有用なんじゃないかと思わないでもない。
配列の後ろに他の配列を追加したいという要件はよくあって、[+](https://www.php.net/manual/ja/language.operators.array.php)や[array_merge](https://www.php.net/manual/ja/function.array-merge.php)では思ったようにいかないことが多いですからね。


## [Deprecate and remove ext/interbase](https://wiki.php.net/rfc/deprecate-and-remove-ext-interbase)

賛成49、反対0で受理。

[Firebird/InterBase](https://www.php.net/manual/ja/book.ibase.php)いらんだろ、というRFC。
今後は[PDO_FIREBIRD](https://www.php.net/manual/ja/ref.pdo-firebird.php)を使うことになります。

そもそもこれを使っている人は居るのだろうか。


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

賛成28、反対5で受理。

弱い参照です。
PHPには既に[WeakRef](https://php.net/manual/ja/class.weakref.php)があるのだけど、それよりさらに弱く、必要最低限の`create`と`get`しかないみたいです。
使いどころは正直よくわかりません。


## [Unbundle ext/wddx](https://wiki.php.net/rfc/deprecate-and-remove-ext-wddx)

賛成30、反対0で受理。

[WDDX](https://www.php.net/manual/ja/book.wddx.php)をPHPコアから削除するRFC。
今後はPECLに移動になります。

WDDXとは異なる言語間でデータをやりとりするための仕組みですが、全く普及しないままXML-RPCやSOAPに取って代わられ、そしてそれらも滅んでJSONにほぼ統一されました。

[wddx_deserialize](https://www.php.net/manual/ja/function.wddx-deserialize.php)には[安全でないデシリアライゼーション](https://blog.tokumaru.org/2017/09/introduction-to-object-injection.html)という仕様上の脆弱性があり、それをどうにかしようという[RFC](https://wiki.php.net/rfc/wddx-deprecate-class-instance-deserialization)が提出されて話し合われたものの、そもそもWDDX自体いらなくね？って展開になったみたいです。


## [New custom object serialization mechanism](https://wiki.php.net/rfc/custom_object_serialization)

賛成20、反対7で受理。

マジックメソッド`__serialize`、`__unserialize`を追加します。

PHPでオブジェクトのシリアライズ方法には[Serializable](https://www.php.net/manual/ja/class.serializable.php)と[`__sleep/__wakeup`](https://www.php.net/manual/ja/language.oop5.magic.php#object.sleep)があるのですが、実は両方とも問題を抱えています。
そこで新たな直列化方法を提供します。

ということらしいのですが問題点が細かすぎてよくわかりませんでした。
複雑な書き方をしたりすると正しくシリアライズできない、ということらしいのですが、そんな複雑な書き方をしない方がよいですよね。
そもそも個人的にはオブジェクトをシリアライズするってことを(無意識のセッション以外)全くしないので、利点も欠点もなんとも言えないのですが。


# Pending

本来PHP7.4で入るはずだったのに、保留行きにされているRFC。
今後の展開次第では7.4に入るかもしれませんし、入らないかもしれません。

## [Deprecate PHP's Short Open Tags](https://wiki.php.net/rfc/deprecate_php_short_tags)

賛成38、反対18で受理。

[short_open_tagが削除](https://qiita.com/rana_kualu/items/180aff848169e1733631)されます。

[やっぱ延長するかも？](https://github.com/php/php-src/pull/3972)みたいな話になっていて、ちょっとどうなるかわかりません。


# 感想

PHP7.4やばすぎでは…？

変更があまりにドラスティックすぎて、PG能力がPHP7.4以前と以後で分断されるんじゃないかレベル。
現状PHP8で入る予定の大きな変更が[JIT](https://qiita.com/rana_kualu/items/ba312d2789bd228f887a)くらいしかないので、もしかしたらPHP7.4→8よりPHP7.3→7.4のほうが大きな差になったりするかもしれませんね。さすがにないかな？