# 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使うと簡潔でセキュリティもよくなりました。
matchswitchよりソースコードが短くなるだけではなく、型チェックもやってくれるので、より厳密になります。

// 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)
2020-12-01
  • php

関連記事

Laravel メンテナンスモード
Laravel でカテゴリー作成 テーブル構築と再帰クエリ
Laravel を API サーバーとしての初期設定
Laravel リクエストログ出力
Laravel 429 Too Many Requests
Laravel Email バリデーションについて
Laravel Sanctum 使って API トークン JWT 認証と SPA 認証
Laravel logger でエラーログを chatwork に自動送信
php CSV データ取得は fgetcsv 使う
Laravel tinker 使って DB データベース接続とコマンド
Laravel Test についてのメモ
Laravel Log の基本設定&使い方
Exception: Class 'ZipArchive' not found
Laravel Sail で Docker 環境構築
PHP 文字列長さ・文字列の幅を取得方法
Codeigniter 画像アップロードとリサイズ
Laravel Lumen Faker 日本語設定
laravel method の基本 get post put options
Laravel schedule 設定
Class 'Imagick' not found Error
Laravel eloquent model の規約
PHP mbconvertkana 全角半角英数カナ変換
Codeigniter APPPATH BASEPATH FCPATH 各種パスと URL 取得
Laravel timestamp() auto update 有効化無効化
Lumen8 で JWT ユーザー認証
Laravel toSql パラメータ付きで出力
Lumen8 で API 開発
php Exception エラーキャッチでメール送信
Smarty HTTP URL 取得できるサーバー関数
Laravel blade foreach loop と current url
laravel session を制する
PHP empty isset is_null の違い
FlattenException deprecated
php.ini 初期設定のいろいろ
Laravel 5.1 から 8.1 にバージョンアップ
PHP 7.4 にアップグレードして使えなくなる機能
開発時によく使うゼロ埋めパディング作業まとめ
解決!phpMyAdmin テーブル構造の内容が表示されない問題
Composer コマンドとオプション
爆速軽量フレームワーク codeigniter PHP 開発
Lumen と Laravel 違い比較
HTML から PDF に変換 PHP ライブラリ mPDF の設定
twig 3 人気 PHP テンプレートエンジンがバージョンアップ
Laravel Error についてのメモ
laravel に vuejs 使うための初期設定
php curl 使って クリックなしで POST 送信
allowurlinclude の設定で ftp_connect()エラー
Carbon で php date 日付の日数・月数差を計算
codeigniter email ライブラリでメール送信 日本語対応
nuxtjs と codeigniter で jwt システム構築
正規表現一覧 よく使う検索・置換のパターン
Apache 初期設定メモ
開発におけるコーディングルール・規約