2020 年末にリリース予定 の PHP 8 の オフィシャル Docker イメージ(library/php
)が Docker Hub に公開されました。
https://hub.docker.com/_/php?tab=tags&page=1&name=8.0-rc-
イメージタグに 8.0-rc
や 8.0-rc-fpm
、8.0-rc-apache
など 8.0-rc
や rc-
のタグが付いているものが現時点では PHP 8 のビルドとなっています。
この Docker イメージを利用して PHP 8 を試してみました。
Hello PHP 8
docker コマンドで php:8.0-rc
イメージを実行するとバージョンに PHP 8.0.0alpha1
となっています!
$ docker run --rm php:8.0-rc php -v PHP 8.0.0alpha1 (cli) (built: Jun 26 2020 19:38:47) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies
Apache httpd + mod_php のイメージである php:8.0-rc-apache
を起動して、phpinfo()
を表示してみます。
$ echo "<?php phpinfo();" > index.php $ docker run --rm -p 8000:80 -v `pwd`:/var/www/html php:8.0-rc-apache
http://localhost:8000
にブラウザでアクセスすると PHP 8 の phpinfo()
が表示されました。
新機能のお試し
PHP 8 環境ができたので、新機能を試してみましょう。
Union Types
https://wiki.php.net/rfc/union_types_v2
型宣言で指定する型を |
で複数指定できる機能です。良し悪しは別にしても、これまで厳密に1つの型にだけ限定できなかったケースが現実的にあるのでそれらに型が付けられるのは良いです。
<?php declare(strict_types=1); // int と string を型指定 $f = function (int|string $v) { var_dump($v); }; $f(100); // ok $f("abc"); // ok $f(true); // ng
実行結果
$ docker run --rm -v `pwd`:/app -w /app php:8.0-rc php union_types.php int(100) string(3) "abc" Fatal error: Uncaught TypeError: {closure}(): Argument #1 ($v) must be of type string|int, bool given, called in /app/union_types.php on line 10 and defined in /app/union_types.php:4 Stack trace: #0 /app/union_types.php(10): {closure}(true) #1 {main} thrown in /app/union_types.php on line 4
Constructor Property Promotion
https://wiki.php.net/rfc/constructor_promotion
コンストラクタ仮引数に可視性を指定することで、プロパティ宣言と引数の省略できる記法です。TypeScript や Scala などにありますね。シンプルに書けるのがうれしいところ。
なお、(1) のように最後の仮引数の後ろにカンマを付けても良いのも PHP 8 の新機能です。( PHP: rfc:trailing_comma_in_parameter_list )
<?php declare(strict_types=1); final class User { public function __construct( public int $id, private string $name, // (1) ){} } // ↓と同じ //final class User //{ // public int $id; // private string $name; // // public function __construct( // int $id, // string $name // ){ // $this->id = $id; // $this->name = $name; // } //} var_dump(new User(1, 'Foo'));
実行結果
$ docker run --rm -v `pwd`:/app -w /app php:8.0-rc php constructor-property-promotion.php object(User)#1 (2) { ["id"]=> int(1) ["name":"User":private]=> string(3) "Foo" }
Attributes
https://wiki.php.net/rfc/attributes_v2
クラスやプロパティ、メソッド(関数)などに付与できるアノテーションです。これまで PHPDoc でやりくりしていたのが言語機能としてサポートされるようになりました。リフレクションで指定された Attributes を取得して処理できます。なお、PHP の Attributes は TypeScript や Python にあるデコレータではないのでご注意を。
<?php declare(strict_types=1); <<PhpAttribute>> final class Attr1 { public function __construct(private string $value) {} } final class Attr2 { public function __construct() {} } <<Attr1("Hello World")>> <<Attr2>> <<NotFound>> class Foo { } $reflectionClass = new \ReflectionClass(Foo::class); $attributes = $reflectionClass->getAttributes(); foreach ($attributes as $attr) { var_dump($attr->getName()); var_dump($attr->getArguments()); // newInstance() は <<PhpAttribute>> が付いたクラスで無いと Fatal Error になる // var_dump($attr->newInstance()); }
実行結果
$ docker run --rm -v `pwd`:/app -w /app php:8.0-rc php attributes.php string(5) "Attr1" array(1) { [0]=> string(11) "Hello World" } string(5) "Attr2" array(0) { } string(8) "NotFound" array(0) { }
Attribute は << >>
以外のシンタックスも検討されているので書き方は今後変わる可能性があります。
https://wiki.php.net/rfc/shorter_attribute_syntax
候補は下記です。今のところ @@
が優勢っぽいですが、どうなるか。
@@
#[]
<< >>
JIT コンパイラ
PHP 8 注目機能の1つでもある JIT コンパイラも試してみました。ここでは、下記のようにフィボナッチ数を再帰で算出するロジックを実行しました。
<?php declare(strict_types=1); $fib = function (int $i) use (&$fib) { return $i < 2 ? $i : $fib($i - 1) + $fib($i - 2); }; var_dump($fib(40));
PHP 8 の JIT コンパイラ機能を有効にするためにいくつか設定が必要なので、それを含めて下記のようなオプションで実行しています。JIT コンパイラは OPCache の機能拡張なので OPCache を有効にする必要があります。また、opcache.jit
や opcache.jit_buffer_size
などで指定する値は PHP: rfc:jit を参考にしています。
$ docker run --rm -v `pwd`:/app -w /app php:8.0-rc php -dzend_extension=opcache \ -dopcache.enable=1 -dopcache.enable_cli=1 \ -dopcache.jit=1235 -dopcache.jit_buffer_size=64M fib.php
実行結果は下記です。JIT on の場合、OPCache on のみより実行時間が 79 % まで短縮しました!
実際の Web アプリケーションでは IO がボトルネックになりがちなので、どれだけパフォーマンスに寄与するか計測は必要ですが、PHP の適用領域を広げる意味でも期待したい機能です。
実行環境 | 実行時間 | |
---|---|---|
[参考] PHP 7.4 (OPCache on) | 12.227s | --- |
PHP 8.0 alpha1 | 12.099s | 106% |
PHP 8.0 alpha1(OPCache on) | 11.398s | 100% |
PHP 8.0 alpha1(JIT/OPCache on) | 9.006s | 79% |
# 参考: PHP 7.4 with OPCache $ time docker run --rm -v `pwd`:/app -w /app php:7.4 php -dzend_extension=opcache \ -dopcache.enable=1 -dopcache.enable_cli=1 fib.php int(102334155) docker run --rm -v `pwd`:/app -w /app php:7.4 php -dzend_extension=opcache 0.03s user 0.02s system 0% cpu 12.227 total # OPCache / JIT off $ time docker run --rm -v `pwd`:/app -w /app php:8.0-rc php fib.php int(102334155) docker run --rm -v `pwd`:/app -w /app php:8.0-rc php fib.php 0.03s user 0.01s system 0% cpu 12.099 total # OPCache on $ time docker run --rm -v `pwd`:/app -w /app php:8.0-rc php -dzend_extension=opcache \ -dopcache.enable=1 -dopcache.enable_cli=1 fib.php int(102334155) docker run --rm -v `pwd`:/app -w /app php:8.0-rc php -dzend_extension=opcache 0.03s user 0.01s system 0% cpu 11.398 total # OPCache / JIT on $ time docker run --rm -v `pwd`:/app -w /app php:8.0-rc php -dzend_extension=opcache \ -dopcache.enable=1 -dopcache.enable_cli=1 \ -dopcache.jit=1235 -dopcache.jit_buffer_size=64M fib.php int(102334155) docker run --rm -v `pwd`:/app -w /app php:8.0-rc php -dzend_extension=opcache 0.03s user 0.01s system 0% cpu 9.006 total
リリーススケジュール
PHP 8 のリリーススケジュールは下記で公開されています。現在の予定では2020/11/26
に GA リリースとなります。
https://wiki.php.net/todo/php80
さいごに
オフィシャル PHP にて PHP 8 のイメージが公開されたので触ってみました。こうして alpha 版リリースの段階でイメージが公開されることは気軽に試すことができてありがたいですね。以前に比べても Docker の活用がさらに広がってきた感じがします。
PHP 8 はまだ Feature freeze されていないので、いくつかの RFC が提案されています。match 式 も通りそうなので今後のリリースが楽しみですね。Docker があれば簡単に利用できるので、PHP 8 を試してみてはどうでしょう。