PHP 8の新機能:知っておくべきことはすべて!

公開: 2021-01-06

2020年11月26日にPHP8と連絡を取ります。確かに、この高く評価されているリリースの今後の機能については多くのことが書かれています。

PHP 8

メジャーバージョンであるため、重大な変更と新機能があり、すべてが何が変更されているかを認識することが重要になります。 PHP8がアプリにどのように影響するか、問題なく便利にアップグレードできるようにするためにどのようなアクションを実行する必要があるかを考えると便利になります。

次のPHPリリースで何が得られるのか、そして何を批判する価値があるのか​​を理解するために、いくつかの最も重要な変更を行いました。

概要から始めましょう!

PHP8の概要

上記のように、PHP 8では、言語に新しい機能、改善、機能、および非推奨のパックが導入されています。 これらすべての中で、最も議論されている機能はJITコンパイラです。 ただし、JITなどのパフォーマンスを向上させる機能は脚光を浴びるに値しますが、構文の改善により、PHPの実践者にとって、「少なくとも短期的には」真の意味での効果が期待されます。

変化の歴史

いくつかのPHPの変更が提案され、議論され、実装され、さらに短い順序で承認されます。 それらは人気があり、議論の余地がなく、それらを実装するための自然な方法があります。

そしてその後、私たちが最終的に受け入れる前に、何度も試され、失敗し、戻ってきたものが来ます。 数回、実装は整理するのに長い時間がかかり、アイデア自体が中途半端な場合もあれば、コミュニティ自体がまだアイデアにウォームアップしていない場合もあります。「まだ時間ではありません」。

クレジットは、タイプカテゴリに直接分類されます。 これらは、2016年にPHP7.1用に最初に提案されましたしかし、彼らは頑固な抵抗に直面し、かなりの差で賛成票を失いました。 さて、4年間早送りし、わずかに縮小されたスコープの提案が1人の反対者だけで浮かび上がったとしてもかなり似ています。 それは明らかにその時が来たアイデアです!

古いコードの問題は何ですか?

PHP 8は巨大な新しいリリースであるため、古いコードとの互換性がなくなることを期待する必要があります。 ただし、複雑さを提案する可能性のある変更の大部分は、バージョン7.2、7.3 および7.4ですでに伝達されています ここで最後の変更について話しましょう。 彼らは:

魔法は遺産を引用します

  • 本当のタイプ
  • FILTER_SANITIZE_MAGIC_QUOTESフィルター
  • 非静的クロージャから$thisのバインドを解除する
  • array_key_exists()とオブジェクト
  • 3番目の引数としてエンコーディングを使用するmb_strrpos()
  • Reflection export()メソッド
  • convert_cyr_string()関数
  • implode()パラメーターの順序の組み合わせ
  • restore_include_path()関数
  • hebrevc()関数
  • money_format()関数
  • allow_url_includeiniディレクティブ
  • ezmlm_hash()関数

PHP8の新機能

str_contains

ある文字列に別の文字列が含まれている場合、それを見つける方法はたくさんあります。

通常、strpos()を使用します。 ご存知のように、strpos()は、探したい針の横にある干し草の山を取ります。 針が見える最初の位置を示す整数を返します。

これで、別の文字列の位置を返すため、strpos()がそれを検出したかどうかを確認することはできません。 「0」(位置はゼロインデックスで、1ではなく0で始まる)を返す場合、条件はそれをfalse値として扱い、見つからなかったことを示します。

どういう意味ですか?

条件付き–「strpos($ haystack、$needle)!==false」と書く必要があります。 Falseは、文字列の位置が見つからなかったことを示します。 これは、文字列内の文字列を検索するための不透明で難解な方法です。 まあ、それほど混乱することはありません。

これを回避するために、PHP 8はstr_contains()を提供します。 str_contains()の役割は、針が干し草の山に存在するかどうかを示す単純なブール値を返すことです。 それ以外に、コードを管理している人として理解する方がはるかに簡単ですよね。

 if (str_contains( 'Foo Bar Baz' , 'Foo' )) { // FOUND }

PHP 8:エンジンの機能と変更

いくつかの新しいエンジン機能と、PHP 8で気づいた変更点があります。ヘッドライニング機能は、間違いなく、新しいJITコンパイラーです。

JITコンパイラ

  • LSP施行
  • 互換性のないメソッドシグネチャの致命的なエラー
  • リソース「クラス」
  • XML-RPCがPECLになりました
  • アサーション動作
  • 反射の変化

このブログの主な目的のために、JITコンパイラ、リソースの「クラス」、そして最後にリフレクションAPIの変更に焦点を当てます。

ジャストインタイムコンパイラ( RFC

PHP7のリリース前に速度が向上したため、Just-In-Time(またはJIT)コンパイラが誕生しました。 JITを使用せずに実現できる速度の向上はほとんどないため、PHP8に導入されています。 アイデアは、PHPのパフォーマンスを向上させることです。

PHPコードは、実行時にバイトコードに変換され、それらのバイトコードは、プログラムのステップを実行するためにさらに利用されます。

PHPは、実行したコードを分析します。これがJITの意味です。 さらに、実行時にコードのパフォーマンスを向上させる以外に、リアルタイムで決定を下すことができます。 これは、Webベースのシナリオで使用されている間だけでなく、CPUを集中的に使用するアプリケーションでも非常に使いやすくなります。

これは、サーバー側のPHPアプリケーションが、PHPに組み込まれたJITシステムでより一般的になる可能性があることを反映しています。

JITを使用する場合は、最初にJITをアクティブ化する必要があります。 テストシステム(Ubuntu 20.04)には、コアPHP8パッケージとともにインストールしたPHPopcacheモジュールが既にインストールされています。 /etc/php/8.0/cli/conf.d/10-opcache.iniにあるファイルで構成しました。

これで、JITをアクティブ化する準備が整いましたね。  

  • opcacheを有効にする

opcache.jit_buffer_size設定にメモリストレージを割り当てることができます。 あなたのファイルは私のシステムではこのように表示されます。

  1. zend_extension = opcache.so
  2. opcache.enable_cli = 1
  3. ; phpopcacheモジュールの構成
  4. opcache.jit_buffer_size = 256M

さらに、opcache_get_status()関数を使用して、アクティブかどうかを確認します。 この配列の「jit」部分に視線を向けて、JITの現在のステータスに関する情報を取得します。


var_dump(opcache_get_status()['jit']);

JITが完全にアクティブ化されている場合、これは下に示すように印刷されます。

  1. array(7){
  2. [「有効」]=>
  3. bool(true)
  4. [“ on”] =>
  5. bool(true)
  6. [「種類」]=>
  7. int(5)
  8. [“ opt_level”] =>
  9. int(4)
  10. [“ opt_flags”] =>
  11. int(6)
  12. [“ buffer_size”] =>
  13. int(268435440)
  14. [“ buffer_free”] =>
  15. int(268432880)
  16. }

それで、それはより速かったですか? 一言で言えば、私たちは暖かい「はい」を叫ぶでしょう。

マンデルブロ集合の助けを借りてベンチマークを行っている人が何人かいることに気付いたので、PHPでいくつかの異なる種類のフラクタルを描画する、少し前に作成したライブラリを使用することにしました。 私たちが行ったのは、3つのフラクタルを生成し、microtome()関数を利用するのにかかった時間を追跡することだけでした。 以下にPHP7.4.8の結果を示します。

  • バーニングシップ– 84.20269203186
  • マンデルブロ– 21.552599906921
  • トライコーン– 32.685042858124

PHP8でまったく同じコードを実行すると、かなり高速になりました。 数字はそれ自体を物語っています。

  • バーニングシップ– 15.272277116776
  • マンデルブロ-3.7528541088104
  • トライコーン-4.4957919120789

この大幅な速度の向上は非常に興味深いものです。 ここで使用したコードは巨大なサイズのフラクタルを作成しますが、コードを作成するときに、ほとんどの時間がフラクタルの生成を待つために費やされたことを覚えています。

この追加は、(フラクタルの生成以外の)場合によってはPHPをその境界に押し上げたため、私たちにとって興味深いものです。 これはPHPの将来にとって非常に有益であり、通常のWebサイト言語以外の状況で言語を選択できるようになることがわかります。

WordPressやDrupalのようなアプリの速度の増加については調べていませんが、私たちが読んだことから、これらの種類のアプリケーションには確かにほとんど違いがありません。 将来的には、これらのプラットフォームでベンチマークを実行して、JITがそこでどのような違いを示すかを把握する予定です。

共用体タイプ( RFC

PHP7以降、どのような戻り値と引数の種類を規定し、可能になりました。 これにより、渡す引数のタイプが予期されたタイプと同一でないソートである場合に、PHPがエラーをスローできるようになります。 関数がPHPなどの緩く型付けされた言語で完全な型の値を受け取り、生成することを保証することが重要です。

PHP8では、引数と戻り値のさまざまな種類をパイプ文字で分割して指定できるようになりました。

以下に、float値または整数値のいずれかを受け入れることができる関数を示しました。

 function addNumbers(int|float $number1, int|float $number2) : int|float { return $number1 + $number2; }

以前は、渡された引数が正しくない場合にPHPが型をサイレントに表示できるため、これと同じ関数を型のヒントなしで生成する必要がありました。 つまり、引数のタイプを整数として設定した場合、PHPはfloat値を整数に表示します。 ユニットテストを行っていない場合に備えて、いくつかのトリッキーなバグを見つけることができます。

上記の関数を使用するために、他の関数と同じように呼び出します

echo addNumbers(1, 1); // prints 2 echo addNumbers(1.1, 1.1); // prints 2.2

同じ関数に文字列を渡そうとした場合:

 echo addNumbers('one', 'two');

関数にfloatまたは「int」を渡す必要があることを示すPHPの致命的なエラーが表示されます。

関数が何も返さないことを規定しているため、void型を共用体型として使用することはできません。 簡単に言うと、関数がvoidまたは整数を返すとは言えません。 PHPの致命的なエラーが発生します。

通常の変更では、この機能が少し使用されていましたが、以前はコメントにさまざまなタイプの値を指定することしかできなかったため、ドキュメントブロックのコメントがコードよりも詳細になりました。

Nullsafeオペレーター(RFC)

null合体演算子に加えて、null戻り値を検出する機能はメソッドから直接可能です。 気づかなかった場合は、null合体演算子を使用して値を取得できます。最初の値がnullの場合に別の値を返す以外に、値が存在するかどうかをテストする必要はありません。

したがって、これを実行して、「$_GETsuperglobal」から値を取得できます。 その値が存在しない場合は、「0」になります。


1. $page = $_GET['page'] ?? 0;

2.エコー$ページ;

nullセーフ演算子の動作は同じですが、便利なショートカットを作成し、その値を使用する前に、ウェイからのnullリターンをテストできます。

これはDrupalで最終的に役立つことに気づきました。そこでは、「メソッドからの戻り値」または「オブジェクトプロパティ」にそれらを使用する前に何かが含まれていることを確認するために、多くのチェックコードを記述する傾向があります。 Drupalのオブジェクトにはコンテンツが含まれているため、オブジェクトのコンテキスト状態のため、これは必須です。 この変更により、いくつかのチェックが確実に簡素化されます。

名前付き引数( RFC

名前付き引数を使用すると、引数の順序を変えて関数を呼び出すことができます。 2つのパラメータを持つ次の通常の関数を取ります。 指定された長さまで配列を埋めます。

 function fillArray(array $arrayToFill, int $number) : array { for ($i = 0 $i < $number; ++$i) { $arrayToFill[$i] =1; } return $arrayToFill; }

引数を定義された配置で渡すことができ、通常の方法でこの手法を呼び出すことができます。

 $newArray = fillArray([], 2);

PHP8以降、関数に渡すときにパラメーターに名前を付けることができるようになりました。 また、パラメータを任意の順序で送信することもできます。

 $newArray = fillArray(number: 2, arrayToFill: []);

通常の例ですが、コードを読みやすくすることもできます。

この手法は、ユーザー定義の関数だけでなく、PHPのすべての関数で機能します。 PHP言語では、配列関数と文字列関数のパラメーターの順序は同じではありません。 だから、それは本当に歓迎すべき追加です。

属性V2( RFC1 RFC2 RFC3

属性は、メタデータをPHPクラス、関数、クラスプロパティ、関数パラメーター、および定数に隣接させるメカニズムを提供します。 コードを介して直接アクセスすることはできません。リフレクションクラスに組み込まれているPHPを使用してそれらを引き出す必要があります。

ReflectionClassクラスはPHP5以降PHPに含まれています。 ただし、getAttribute()メソッドはPHP8の新機能です。 このメソッドは、属性に関する情報を受け入れる一連のReflectionAttributeオブジェクトを返します。

この追加はいくつかの変更に直面しました(上記の複数のRFCからわかるように)。 クラスをインスタンス化する場合は、ReflectionClassを使用して、クラスレベルに含まれる属性情報を出力できます。 PHP8には属性がたくさんあるので、RFCを読んで、RFCが実際に何であるか、およびそれらをコードに統合する方法を理解することをお勧めします。

一致式( RFC

PHP 8では、新しいmatch式を簡略化されたswitchステートメントと比較できます。

渡された値に基づいて値を返す関数宣言に少し似ています。

PHPのswitchステートメントは、複数のifステートメントをまったく含めずに、同一の式の条件をチェックしたい場合に最適です。

ここでは、同じ式の基本的なif-else比較を示します。

 <?php if ($i == 'apple') { echo 'i is apple'; } elseif ($i == 'cake') { echo 'i is cake'; } else { echo 'i is pizza'; }

これは、前の例の同等のswitchステートメントがどのように表示されるかを示しています。

 <?php switch ($i) { case 'apple': echo 'i is apple'; break; case 'cake': echo 'i is cake'; break; default: echo 'i is pizza'; }

リソース「クラス」

リソースの「クラス」は、PHP 8の主要な変更点のリストに含まれており、特定のリソースタイプのインスタンス化できない代替として機能します。 利用可能な代替品を知るには、以下を参照してください。

  • CurlHandle — curl_init()は、curlリソースに関連するCurlHandleを返すようになりました。
  • Socket / AddressInfo —ソケット拡張によって与えられます。 socket _ *()関数の数はSocketを返し、socket_address_info_lookup()関数はAddressInfoインスタンスを返します。
  • GdImage —多数のimagecreatefrom *()関数によって復元されたGDリソースを表します。

また、curl_close()などの関数によってリソースが破壊されないことに注意することが重要です。 むしろ、インスタンスがクラスインスタンスになっているため、インスタンスをunset()して参照を解除する必要があります。
関数とメソッドでクラスをタイプヒントとして指定できるようになります。
以前は、型指定されていない値を返すか、リソース引数を残してアノテーションを介してそれらを文書化する必要がありましたが、今では明示的な型を使用できるようになり、コードが読みやすくなるだけでなく、型の安全性も向上します。
ここでのトレードオフは何ですか?
リソースを破棄するために使用されていた以前の関数の代わりにunset()を使用してリソースを破棄する場合は、コードを更新する必要があります。 これは通常、検索と置換によって実現できます。

リフレクションAPIの変更

もう1つ小さなものですが、PHP 8の重要な変更は、ReflectionAPIに関連しています。 属性システムを使用している間、どのリフレクションクラスでもReflectionAPIを介してこれらの属性を簡単に取得できます。
混合型と共用体型の追加により、ReflectionParameterテクニックのgetClass()、isCallable()、およびisArray()は非推奨になりました。
シナリオは、getType()を使用する方がはるかに優れており、特定のパラメーターが満たすタイプの完全なリストを取得するためです。

PHP8構文の改善

私たちが気付いているように、JITは見出しを盗んでいます。 PHP 8の構文上の改善により、PHP開発者は生活の質を大幅に向上させることができます。
昇格したコンストラクター引数に共通する定型文を排除したり、例外やエラー処理を改善したりしても、開発者は興奮することがたくさんあります。

  • 「混合」疑似タイプ
  • 共用体の種類
  • クラスコンストラクタプロパティの昇格
  • 式から例外をスローする
  • 属性
  • ::クラスユビキタス
  • タイプのみでキャッチ
  • 一致式

このブログの目的を維持するために、共用体の型、属性、および一致式に焦点を当てています。

共用体の種類

共用体タイプは、値が2つ以上の指定されたソートのうちの1つであることを示します。 これは、許可されているすべてのタイプの間に垂直バーを配置して行われます。 PHPアノテーションを深く理解して値を返したり、パラメーターを指定したりする開発者の場合、おそらくこれをすでに行っています。
共用体型は、多くの異なる型を受け入れるか、または多くの異なる型を返す人にとって、理解するのに非常に複雑で困難をもたらす可能性があります。
それでも、これはいくつかの場面で非常に役立ちます。 たとえば、新しいStringableインターフェイスを実装するオブジェクト(「string | Stringable」)または文字列を受け入れることができる場合、またはTraversableインターフェイスを実装するオブジェクト(「array | Traversable」)または配列を受け入れることができる場合。

一致式

一致式は、特定のスイッチケース内での失敗が意図的であるかどうかを判断することに関連する推測を遮断します。 また、一致に基づいて値を割り当てる通常のパターンを簡素化します。
使用すると、match()に渡す値は、左側にある式と直接比較されます。 それが式であろうと値であろうと、match()に渡す値は、それが選択されるためにそれに一致する必要があります。
一致すると、右側に存在する式が推定され、その戻り値が返されますが、式はLambdaまたはcallables関数のみであり、複数行のクロージャは許可されません。

属性

PHP 8は、言語レベルでも属性を統合します。 属性はdocblockアノテーションを介して15年以上存在しますが、属性を言語に組み込むと、パフォーマンスが向上し、確かに、より強力で一貫性が高まります。 ツーリングや迅速なアプリケーションの開発で属性が頻繁に使用されていることがわかります。

結論

確かに、PHP8にはいくつかの変更が加えられています。 それでも、廃止されたコードの大部分は、最近使用されていない古い機能のためのもののようです。
JITエンジンが、使用するコードベースとより広いPHPコミュニティにどのような影響を与えるかについては、非常に興味があります。コードベースをスキャンしてPHP8との非互換性を確認し、単体テストを実行してPHPを確認することを強くお勧めします。アップグレードに「はい」と言う前に、アプリケーションは完全に機能します。