# PHP 8 リリース新機能と変更
php 8 は 2020 年 11 月 26 日にリリースされました!🎉
誕生してから 25 年に迎えた PHP が時代とともに進化していて未だに現役で活躍しています。速度倍以上にアップした 2015 年に PHP7 リリースから 5 年、PHP8 が更に速い実行速度でやって来ました。
PHP7 も速いですが、PHP8 になって長時間実行するプログラムは更に1.5 ~ 2 倍の処理速度向上します。
# JIT 実行時コンパイラ
JIT コンパイラー とは
Just In Time Compiler 翻訳すると実行時コンパイラといいます。AOT(Ahead-Of-Time)事前コンパイラとは違ってプログラムが実行されるその時に CPU の機械語に変換(コンパイル)することが JIT です。
さらにさらに、従来よく使うプログラムをメモリにキャッシュしたことをコンパイル済みの機械語をキャッシュするようになり、今回 PHP8 の速度が大幅に改善された原因だそうです。
実際の体感はいろいろでしょうが、1 分かかる処理が 8 秒に完了するとかの話がありました。ワクワクしますね!
# 名前付き引数
名前付き引数 Named arguments (opens new window)
これまで引数の順番を知らないと配列操作できなかったが、json 感覚に引数定義できるようになりました。
// php8新機能
array_fill(start_index: 0, num: 100, value: 50);
// php7
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
// php8
htmlspecialchars($string, double_encode: false);
# アトリビュート
アトリビュート Attributes (opens new window)
アトリビュートは、doc-block コメントと同様に、それらが属する宣言の前に追加されます。それらは、宣言を文書化する doc-block コメントの前または後に宣言できます。
// php8新機能
<< WithoutArgument >>
<< SingleArgument (0 )>>
<< FewArguments ('Hello' 、 'World' )>>
function foo(){ }
// php7
class php7PostsController
{
/**
* @Route("/api/posts/{id}", methods={"GET"})
*/
public function get($id) { /* ... */ }
}
// php8
class php8PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
# コンストラクタ プロパティ
コンストラクタ プロパティ Constructor property promotion (opens new window)
これまでプロパティ宣言して代入する作業の二回定義する必要なものを一回に簡略。
// php7
class Point {
public float $x;
public float $y;
public float $z;
public function __construct(
float $x = 0.0,
float $y = 0.0,
float $z = 0.0,
) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}
//php8
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
# ユニオン タイプ
ユニオン タイプ Union types (opens new window)
PHP の特徴でもある複数の型を受け取る、返すことを定義制約できるようになります。
// php7
class Number {
/** @var int|float */
private $number;
/**
* @param float|int $number
*/
public function __construct($number) {
$this->number = $number;
}
}
new Number('NaN'); // Ok
// php8
class Number {
public function __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
# マッチ式
マッチ式 Match expression (opens new window)
これまでのswitchが使いにくかったが、match使うと簡潔でセキュリティもよくなりました。
matchはswitchよりソースコードが短くなるだけではなく、型チェックもやってくれるので、より厳密になります。
// php7
switch (8.0) {
case '8.0':
$result = "Oh no!";
break;
case 8.0:
$result = "This is what I expected";
break;
}
echo $result;
//> Oh no!
// php8
echo match (8.0) {
'8.0' => "Oh no!",
8.0 => "This is what I expected",
};
//> This is what I expected
// 新機能
echo match ($x) {
1, 2 => 'Same for 1 and 2',
3, 4 => 'Same for 3 and 4',
};
# ヌル安全オペレータ
ヌル安全オペレータ Nullsafe operator (opens new window)
これまでnullチェックするためのソースが確かに長過ぎるから、PHP8 では改善されました。javascript のように一行で null チェックができるのがかっこいい!
// php7
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
// php8
$country = $session?->user?->getAddress()?->country;
// bar()、baz()は実行されない
null?->foo(bar())->baz();
# 文字と数値比較
文字と数値比較 Saner string to number comparisons (opens new window)
文字列と数値を比較する場合、これまでは文字列を数値に変換してから比較していましたが、今後はより厳密に数値を文字列に変換してから比較するようになります。
// php7
0 == 'foobar' // true
// php8
0 == 'foobar' // false
厳密と非厳密比較の違い
文字列と数値を比較する場合 php8 は数値を文字列に変換してから比較
非厳密な比較== != > >= < <= <=>はこの変更で影響されます!
| 比較項目 | 厳密な比較 | 非厳密な比較 |
|---|---|---|
| 文字列 | 文字列をセマンティクスと比較 | 文字列が数値の場合は数値として扱う「スマート」比較 |
| 配列 | キーが同じ順序必要 | キーが同じ順序必要ない |
| オブジェクト | オブジェクト ID で比較 | オブジェクトの値を比較 |
| 比較 | PHP7 | PHP8 |
|---|---|---|
| 0 == "0" | true | true |
| 0 == "0.0" | true | true |
| 42 == "42" | true | true |
| 0 == "foo" | true | false |
| 0 == "" | true | false |
| 42 == "42foo" | true | false |
| "0" == "0" | true | true |
| "0" == "0.0" | true | true |
| "0" == "foo" | false | false |
| "0" == "" | false | false |
| "42" == "42" | true | true |
| "42" == "42foo" | false | false |
var_dump((int)"foo"); // int(0)
var_dump((int)"" ); // int(0)
var_dump((int)"42foo"); // int(42)