PHP7.3.0がリリースされた & Windowsで試してみる

2018/12/06、日本時間の2018/12/07早朝あたりにPHP7.3.0が[リリースされました](http://php.net/archive/2018.php#id2018-12-06-1)。

7.2からの変更点に関しては[過去](https://qiita.com/rana_kualu/items/48e6e4baaeb265ab9fa7)[幾度か](https://qiita.com/rana_kualu/items/a7c6be77e165bca0f3fc)[記事に](https://qiita.com/rana_kualu/items/05a510f53c0ea9a1ccaf)[して](https://qiita.com/rana_kualu/items/12ff6d448c0d5ad73108)いますが、これらの機能が正式に使えるようになりました。
公式の移行マニュアルは[日本語](https://php.net/manual/ja/appendices.php)はまだ来ていません。
[英語版](https://php.net/manual/en/appendices.php)を参照するとよいでしょう。


# Windowsへのインストール

Windowsには[phpbrew](http://phpbrew.github.io/phpbrew/)のような便利ツールはないので、統合パッケージである[XAMPP](https://www.apachefriends.org/jp/index.html)を使うことにします。
Docker？Vagrant？うるせーしるか

## XAMPP

執筆時点での最新版、PHP7.2.12をダウンロードして、インストールする。
既にXAMPPがインストールされているようであれば、一度アンインストールする。
アンインストール中に『htdocsを削除するか？』と聞かれるので、Noを選んでおこう。

そして同じディレクトリに最新版をインストールしようとすると『The selected folder is not empty』と言われる。ファック

個人的にXAMPP最大の欠点はここだと思っていて、何故かアップグレード機能がないんですよね。
`conda update conda`あたりを見習ってほしいところ。

最新版は適当に新規ディレクトリにインストールして、htdocsは旧ディレクトリからコピーするなりシンボリックリンク[^1]貼るなりするとよいでしょう。

## PHP7.3.0

せっかくインストールされたPHP7.2.12ですが、一度も日の目を見ることはありません。

[PHP for Windows](https://windows.php.net/download)から『PHP 7.3.0 VC15 x86 Thread Safe』をダウンロードし、中身を全部XAMPP/phpディレクトリにぶちまける。
これでインストール完了。

なお、ここはx64ではありません。
どうもXAMPPに入っているApacheは32ビット版らしく、x64を入れると死にます。残念。
まあ、所詮動作確認して遊ぶだけなので適当でいいでしょう。


## 起動 & 設定

Apacheを起動してlocalhostにアクセスするとPHP7.3.0になっているはず。簡単。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/26088/9d0457e9-da92-4528-143d-1efa779fdecf.png)


気に入らない設定などがあれば`php.ini`で対処しよう。

必ずやっておくべきことは
・`error_reporting=E_ALL`にする
・`date.timezone=Asia/Tokyo`にする

個人的お勧めは
・`extension=gmp`のコメントを解除

あとXAMPPの`php.ini`には何故か古の`register_globals`・`mysql.allow_local_infile`といった設定が残っているのだが、動くことはないので気にしなくてもよい。
気になるなら適当に削除しよう。


# 新機能を試してみる

```php

// ヒアドキュメント改善
$text = <<< EOF
          a
        b
      c
      EOF;

var_dump($text);
/* ↓こうなる
    a
  b
c
*/

// 末尾カンマ
	$a = [1,2,];
	$b = (new \DateTime())->format('Y-m-d H:i:s', );
	var_dump($a, $b, );


// JSONの例外
	try {
	    $invalidJson = 'hoge';
	    json_decode($invalidJson, true, 512, JSON_THROW_ON_ERROR);
	} catch (JsonException $e) {
	    echo
	    $e->getMessage(), // Syntax error
	    json_last_error_msg(); // No error
	}

// listのリファレンス
	$array = [1, 2];
	list($a, &$b) = $array;

	$a = 4;
	$b = 5;
	var_dump($array); // [1, 5]

// ネットワークインターフェイスを取得
	var_dump(net_get_interfaces());

// array_key_last
	echo array_key_first([1, 2, 3, 4]); // 0
	echo array_key_last([1, 2, 3, 'a'=>4]); // a

// Argon2id
	echo password_hash('password', PASSWORD_ARGON2ID, [
	    'memory_cost' => 1 << 17,
	    'time_cost' => 4,
	    'threads' => 2,
	]); // →のような文字列になる $argon2id$v=19$m=131072,t=4,p=2$R08vOXBNTldadFB3czhaMg$/6vBWLkvKMrx/tf+Cl99TmS50nmSr/xgFUlaiavTOlU

// defineの第三引数削除
    define('FOO', 'BAR', true); // Deprecated: define(): Declaration of case-insensitive constants is deprecated
    echo FOO; // BAR
    echo foo; // BAR Deprecated: Case-insensitive constants are deprecated

// assert
namespace HOGE;
    function assert(){} // Deprecated: Defining a custom assert() function is deprecated

// setcookie
	setcookie('hoge', 'fuga', [
	    'expires' => 3600,
	    'path' => '/',
	    'secure' => true,
	    'httponly' => true,
	    'samesite' => 'Strict',
	    'foo' => 'bar', // Warning: setcookie(): Unrecognized key 'foo' found
	]);

// GMP関数
	echo gmp_binomial(10, 5); // 252 ( = 10C5 )
	echo gmp_lcm(14, 11); // 154 最小公倍数
	echo gmp_perfect_power(27); // 累乗数であればtrue
	echo gmp_kronecker(5, 6);// 1 ←？
```

リリース版だから当然と言えば当然ですが、ひととおり問題なく使えました。

ただgmp_kroneckerは何なのかよくわかりません。
内部的には単に[mpz_kronecker](https://machinecognitis.github.io/Math.Gmp.Native/html/54ba330f-67d3-fa30-2d5f-0480b7f4659c.htm)を呼んでるだけでした。

以上はこれまで紹介してきたものですが、それ以外にも変更が多少あるようです。

## MBString support for full case-mapping and case-folding

```php
echo mb_strtoupper('Straße'); // STRASSE
```

PHP7.2までは`STRASE`ですが、7.3からは正しく`STRASSE`に[なります](https://3v4l.org/0ffOq)。
まあ、本当にこれで正しいのかよくわからないのですが。

## LDAP Controls Support

ldap_add他、LDAP関数の引数に[LDAP controls](https://php.net/manual/en/ldap.controls.php)が追加されました。
[英語版](https://php.net/manual/en/function.ldap-add.php)のマニュアルには既に記載されていますが、[日本語版](https://php.net/manual/ja/function.ldap-add.php)にはまだありません。

## Improved FPM Logging

グローバルオプションlog_limit・log_buffering・decorate_workers_outputが追加されました。
[Long messages into stdout/stderr are truncated incorrectly](https://bugs.php.net/bug.php?id=69031)というバグへの対応のためのようです。
1024文字とかの長いログを出さなければ特に関係ないと思われます。


# 感想

[PHP Intelephense](https://github.com/bmewburn/vscode-intelephense)は新文法に未対応で、文法エラー吐きまくりです。
というか作者の足取りが[2018年3月から突然途絶えてる](https://github.com/bmewburn)のだが大丈夫か。

PHP7.3は目玉となる新機能はヒアドキュメントと末尾カンマくらいで、あまりドラスティックな変化こそありませんが、地味で目立たないながらも地道な改善・パフォーマンス向上が多数行われています。
7.2からの互換性が壊れる点もほとんどないので、既にPHP7.2環境であるなら、さくっと7.3に上げてしまってもほとんど問題ないでしょう。
7.0、7.1からであれば、互換性のない点もそれなりにあるので、移行ガイドなどを参照しつつ対応していきましょう。

5.xなら今すぐ予算組んで7.2にアプグレしろ。


[^1]: ショートカットではない。