PHP 7.2の新機能

PythonとGoを積極的に使用しているにもかかわらず、サーバーコードの大部分はPHPで記述されています。 そのため、私たちは言語のすべての革新を注意深く追っています。 前のマイナーバージョンのリリースから1年足らずで、8月17日に最後のベータリリースが予定されています。 実稼働環境での使用はまだ推奨されていませんが、既にdocker imageをダウンロードできます。 言語の新しいバージョンで何が変わったのかを理解する時が来ました。









内容





最適化



Opcacheは、静的な単一割り当てフォーム(SPA)を使用したデータフローの分析に基づくグローバルな最適化を追加しました。スパース条件付き定数伝搬(SCCP)、デッドコード除去(DCE)、および未使用のローカル変数の削除です。







in_array()



組み込み関数は、逆配列のハッシュを検索することによりin_array()



れています。







新機能



名前で拡張機能をダウンロードする機能を追加しました( RFC



以前は、php.iniファイルのextension=



およびzend_extension=



には、拡張ファイルへのパスが含まれていました。

しかし、残念ながら、ファイル名はプラットフォームに依存していました。 たとえば、unixライクなシステムでは、 <extension-name>.<suffix>



として構築され、 HP-UXを除くすべてのシステムで、 .so



である場合、 suffix



.so



です。 Windowsでは、ファイル名はphp_<extension-name>.dll



として形成されphp_<extension-name>.dll



。 これはすべて多くの間違いを引き起こしました。







今、あなたは書くことができます:







 extension=bz2 zend_extension=xdebug
      
      





また、OSに応じて必要な拡張機能がロードされます。







このメカニズムは、iniファイルでextensionおよびzend_extensionを設定するときに機能し、 dl()



関数の引数としても機能します。







ただし、絶対パスを指定する場合と同様に、CLIモードで-z



フラグを使用して絶対パスを指定する必要があります。 次の例は機能しません。







extension=/path/to/extensions/bz2









抽象関数( RFC )をオーバーロードする機能を追加



これで、通常の関数と同じ方法で抽象関数をオーバーロードできます。







 abstract class A { abstract function bar(stdClass $x); } abstract class B extends A { abstract function bar($x): stdClass; } class C extends B { function bar($x): stdClass{} }
      
      





PHP 7.2より前の形式のエラー:







Fatal error: Can't inherit abstract function A::bar() (previously declared abstract in B)









-0( RFC )を返すことを禁止されたnumber_format()



number_format(-0.00)



への呼び出しはstring(1) “0”



number_format(-0.01)



number_format(-0.01)



string(2) “-0”



返しました。 これで0が符号なしで返されます。







オブジェクト/配列( RFC )をキャストするときに番号付きキーを変換する機能を追加



背景:







PHPには、キー/値を含む2種類のデータがあります。 1つ目は配列で、文字列または数字の形式でキーを含めることができます。 また、文字列がルール/^(0|(-?[1-9][0-9]*))$/



PHP_INT_MIN ≤ n ≤ PHP_INT_MAX



、非常に小さいPHP_INT_MIN ≤ n ≤ PHP_INT_MAX



、数値キーに変換されます。







2番目のタイプは、数値キーが許可されておらず、キーが文字列に変換されるオブジェクトです。







同時に、Zend Engineでは単一のHashTable



構造として表示されます。







これは現在修正されています。







いくつかの例を見てみましょう。







 $obj = new stdClass; $obj->{'0'} = 1; $obj->{'1'} = 2; $obj->{'2'} = 3; $arr = (array) $obj; var_dump($arr); // ,    / var_dump($arr[1]); //     .  PHP 7.2  .
      
      





 $arr = [0 => 1, 1 => 2, 2 => 3]; $obj = (object)$arr; var_dump($obj); // ,    / var_dump($obj->{'0'}); //     .  PHP 7.2  .
      
      





get_class()( RFC )にパラメータとしてnullを渡すことは禁止されています



クラスコンテキスト内のget_class()



パラメーターとしてnullが渡されると、関数の動作は非常に予期しないものになる可能性があります。







 class Foo { function bar($repository) { $result = $repository->find(100); return get_class($result); } }
      
      





$result



にリポジトリから返された有効なオブジェクトが含まれる場合、関数の結果はこのオブジェクトのクラス名になります。







$result



null



が含まれる場合、出力にはget_class()



が呼び出されるクラスコンテキストget_class()



この場合はFoo



get_class()



が含まれnull









この機能は、「必要な関数のサプライズ係数が高い場合、この関数の再設計が必要になる可能性があります」という最小限の驚きの原則に違反しています。

これで警告が発行されます:

Warning: get_class() expects parameter 1 to be object, null given in %s on line %d





古い動作を維持する場合は、コードを書き直す必要があります。







 // : $x = get_class($some_value_that_may_be_null); // : if ($some_value_that_may_be_null === null) { $x = get_class(); } else { $x = get_class($some_value_that_may_be_null); }
      
      





カウントできないパラメーターを使用した呼び出しカウント( RFC



現在、スカラー、null、またはCountableインターフェイスを実装していないオブジェクトのパラメーターを指定してcount()



を呼び出すと、 Warning



が生成されます。







パラメータタイプの拡張性( RFC



最もホットに議論された変更の1つは、後継でパラメーターのタイプを指定しない機能です。 したがって、相続人はあらゆるタイプのパラメータを受け入れることができます。







 class ArrayClass { public function foo(array $foo) { /* ... */ } } class EverythingClass extends ArrayClass { public function foo($foo) { /* ... */ } }
      
      





PHP 7.2より前では、エラーが返されました。







 Warning: Declaration of EverythingClass::foo($foo) should be compatible with ArrayClass::foo(array $foo) in %s on line 18
      
      





意見はプルリクエストで分かれました

いくつかは言った:







「もちろん、SOLIDを地獄に送りましょう。バーバラリスコフとは誰ですか?ある種の狂った女性ですか?もちろん!原則とアイデアを打ち破りましょう。」

他の人は信じています:







「単一責任(単一責任)の原則のような制限は、言語レベルではなく、アプリケーションコードで実装する必要があります。SOLIDの文字Lは、開発者の裁量になります。」


グループ化された名前空間の末尾にカンマを指定する機能が追加されました( RFC



 //       $array = [1, 2, 3,]; //      use Foo\Bar\{ Foo, Bar, Baz, };
      
      





この機能を他のリストに追加することも計画されていましたが、投票段階でキャンセルされ、引き続きParse error



が返されParse error









 //     fooCall($arg1, $arg2, $arg3,); //    class Foo implements FooInterface, BarInterface, BazInterface, { //   use FooTrait, BarTrait, BazTrait, ; //     const A = 1010, B = 1021, C = 1032, D = 1043, ; protected $a = 'foo', $b = 'bar', $c = 'baz', ; private $blah, ; //     function something(FooBarBazInterface $in, FooBarBazInterface $out,) : bool { } } //         $foo = function ($bar) use ( $a, $b, $c, ) { // . . . };
      
      





socket_getaddrinfo( RFC )ファミリーの関数を実装しました



これで、Cで実装されたgetaddrinfo()



からの情報がPHPから利用可能になりますが、これは現在のソケットライブラリにない機能です。 さまざまなネットワークを操作する場合、 libc



にヒントのセットが与えられると、どの接続/リスニングメソッドが最適かを教えてくれると便利です。







4つの機能が承認されました。







 socket_addrinfo_lookup(string node[, mixed service, array hints]) : array socket_addrinfo_connect(resource $addrinfo) : resource socket_addrinfo_bind(resource $addrinfo) : resource socket_addrinfo_explain(resource $addrinfo) : array
      
      





TLS定数( RFC )の改善



今:









オブジェクトのタイプヒント( RFC



ヒントの新しいタイプを追加しました: object









 function acceptsObject(object $obj) { // ... } acceptsObject(json_decode('{}')); acceptsObject(new \MyObject()); acceptsObject(" "); function correctFunction() : object { $obj = json_decode('{}'); return $obj; } //   function errorFunction() : object { return []; }
      
      





LDAP EXOP( RFC



php-ldapで高度なLDAP操作を使用するために追加された関数。







 //  EXOP whoami     $identity if (ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, $identity)) { echo "Connected as $identity\n"; } else { echo "Operation failed\n"; } //    ,   : $r = ldap_exop($link, LDAP_EXOP_WHO_AM_I); if (($r !== FALSE) && ldap_parse_exop($link, $r, $retdata)) { echo "Connected as $retdata\n"; } else { echo "Operation failed\n"; } //     : if (ldap_exop_whoami($link, $identity)) { echo "Connected as $identity\n"; } else { echo "Operation failed\n"; } //    : if (ldap_exop_passwd($link, 'uid=johndoe,dc=example,dc=com', '', 'newpassword')) { echo "Password changed\n"; } else { echo "Operation failed\n"; }
      
      





PHPコアに追加されたLibsodium( RFC



Libsodiumは、認証された暗号化、楕円曲線を使用した高速暗号化などを提供する最新の暗号化ライブラリです。 他の暗号化標準(WebCryptoなどの暗号化プリミティブのセット)とは異なり、libsodiumには、セキュリティの専門家によって実装された慎重に選択されたアルゴリズムが含まれています。 これにより、サードパーティのチャネルの脆弱性を回避できます。







Argon2パスワードハッシュアルゴリズムが追加されました( RFC



Argon2は、メモリの高速充填と複数のコンピューティングユニットの効率的な使用を目的とした最新のシンプルなアルゴリズムです。







オブジェクトとしてのHashContext( RFC



PHP5以降、オブジェクトは内部データを保存するための好ましい構造でした。 何らかの理由で、Hash拡張機能はこれにリソースを使用しました。 このRFCは、ハッシュ拡張機能を翻訳して内部データをオブジェクトとして保存することにより、誤解を修正しようとしています。







内部表現としてリソースを使用する例:







 resource hash_copy ( resource $context ) resource hash_init ( string $algo [, int $options = 0 [, string $key = NULL ]] )
      
      





内部表現は、リソースからオブジェクトに変換されます。 明示的なis_resource()チェックを使用しない場合、既存のコードは引き続き動作します。これらのチェックはis_resource |に簡単に置き換えることができます。 is_object。







PDO Prepared Statement( RFC )デバッガーを追加



 $db = new PDO(...); $stmt = $db->query('SELECT 1'); var_dump($stmt->activeQueryString()); // => string(8) "SELECT 1" $stmt = $db->prepare('SELECT :string'); $stmt->bindValue(':string', 'foo'); //      var_dump($stmt->activeQueryString()); // => string(14) "SELECT :string" //      $stmt->execute(); var_dump($stmt->activeQueryString()); // => string(11) "SELECT 'foo'"
      
      





PDO Prepared Statements v2( RFC )デバッガーを追加



 $calories = 150; $colour = 'red'; $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?'); $sth->bindParam(1, $calories, PDO::PARAM_INT); $sth->bindValue(2, $colour, PDO::PARAM_STR); $sth->execute(); $sth->debugDumpParams(); /* : SQL: [82] SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ? Sent SQL: [88] SELECT name, colour, calories FROM fruit WHERE calories < 150 AND colour = 'red' Params: 2 Key: Position #0: paramno=0 name=[0] "" is_param=1 param_type=1 Key: Position #1: paramno=1 name=[0] "" is_param=1 param_type=2 */
      
      





PDO( RFC )の高度な文字列型



 $db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL); // N'über' $db->quote('A'); // 'A' $db->setAttribute(PDO::ATTR_DEFAULT_STR_PARAM, PDO::PARAM_STR_NATL); $db->quote('über'); // N'über' $db->quote('A', PDO::PARAM_STR | PDO::PARAM_STR_CHAR); // 'A'
      
      





オプションJSON_INVALID_UTF8_IGNOREおよびJSON_INVALID_UTF8_SUBSTITUTE( Request )が追加されました



json_encode



/ json_decode



、無効なUTF-8バイトシーケンスを無視または置換するために、新しいオプションJSON_INVALID_UTF8_IGNORE



およびJSON_INVALID_UTF8_SUBSTITUTE



た。







PHP 7.2から削除



次の機能は廃止され、削除されました。







引用符のないバー(むき出しの単語)( RFC )は削除されました



引用符のない行はE_WARNING



呼び出すようになりました。 PHP2では、このような行によりSyntax error



Syntax error



しましたが、PHP3ではベータ版の動作が変更されました。

例:







 $foo = flase; // ,     E_NOTICE,   . // ... if ( $foo ) { var_dump($foo); // string(5) "flase" }
      
      





mcryptをPECLに移植する



PHP 7.1で非推奨になったmcrypt拡張機能は、PECLに移動しました。







PHP 7.2で非推奨( RFC



次の機能は廃止され、推奨されなくなりました。

この機能はバージョン8.0で削除されます。







非推奨の__autoload



spl_autoload_register



関数は、バージョン5.1でspl_autoload_register



に置き換えられました。

spl_autoload_register



の主な利点は、複数のオートローダーを使用できることです。 これで、コンパイルの段階で非Deprecation notice



がスローされます。







非推奨のpng2wbmp()およびjpeg2wbmp()



Png2wbmp()



およびjpeg2wbmp()



は、直接呼び出すことができるイメージの形式を変更する唯一の関数であり、 ext / gd



で使用できます。libgdはそのような関数を提供しないため、非常に孤立します。 さらに、 WBMP



WAP



をサポートするために発明されましたが、現在は古くなっています。 これで、 Deprecation notice



がスローされます。







非推奨の$ php_errormsg



track_errors



パラメーターtrack_errors



有効(デフォルトでは無効)で、エラーハンドラーがエラーをインターセプトしなかった場合、致命的でないエラーが発生すると、 $php_errormsg



がローカルエリアに作成されます。







動作がiniファイルの設定に依存するという事実に加えて、それも魔法のようでした。 error_get_last



関数は、最新のエラーを取得するよりクリーンな方法を提供します。 PHP 7以降、 error_clear_last



関数がerror_clear_last



になりました。したがって、スコープを操作することなく、 $php_errormsg



考えられるすべての使用をカバーしています。







非推奨のcreate_function()



create_function()



は、 eval()



言語構成体を囲む薄いシェルであり、生成された名前、引数のリスト、および文字列引数としての本体を使用して関数を作成できます。 PHP 5.3でクロージャーを導入する前は、ラムダ関数に似たものを作成する方法を提供していました。







作業の性質により、潜在的なセキュリティ問題の原因に加えて、 create_function()



パフォーマンスとメモリ使用量の特性は非常に劣っています。 あらゆる方法で実際のクロージャーを使用することが望ましいです。







非推奨のmbstring.func_overload



iniファイルのmbstring.func_overload



パラメーターを使用すると、文字列関数の特定のサブセットを、mbstring拡張機能を持つ類似物に置き換えることができます。 たとえば、 strlen()



は文字列の長さをバイト単位で返さなくなり、代わりに、現在選択されている内部エンコーディングに従って文字単位の長さを返します。







これは、 mbstring.func_overload



を使用するコードmbstring.func_overload



、基本的な文字列操作が正常に機能するという仮定の下で記述されたコードと互換性mbstring.func_overload



ないことを意味します。 一部のライブラリはfunc_overload



(Symfonyなど)を明示的に禁止していますが、他のライブラリは動作を停止します。 func_overloadをサポートするコードは、通常の文字列関数と8ビットエンコーディングのmbstring関数を条件付きで切り替える必要があります(通常、暗号化ライブラリのみがこれを試みます)。

mbstring.func_overload



にゼロ以外の値が含まれている場合、非Deprecation notice



がスローされるようになりました。







非推奨(未設定)キャスト



キャスト(unset)



は、値をNULLにします。 これは、 (unset) expr



は常にnullを返すだけの式であり、他の副作用がないことを意味します。

無駄に加えて、この動作は紛らわしいだけです。なぜなら、多くの人は(unset) $a



(unset) $a



unset($a)



と同様に振る舞うと合理的に仮定しているからです。

これで、コンパイルの段階で非Deprecation notice



がスローされます。







2番目の引数のない非推奨のparse_str()関数



parse_str()



関数は、URL文字列を解析し、現在のコンテキストの変数に値を割り当てます(または、結果パラメーターが指定されている場合は配列に値を入れます)。







関数のスコープ内で変数を動的に作成するとregister_globalsとまったく同じ問題が発生するため、結果パラメーターなしでこの関数を使用することは非常に推奨されません。 結果パラメーターが渡されない場合、非Deprecation notice



スローされるようになりました。







非推奨のgmp_random()関数



gmp_random()



関数は、乱数を生成します。 数値は、数値リミッターの積に四肢(リム)のビット数が乗算されるまで、ゼロの範囲になります。 リミッター番号が負の場合、負の結果が返されます。







リムは内部GMPメカニズムです。 技術的には、これは1つの機械語に適合する数の一部です。 その中のビット数はシステムによって異なる場合があります。 基本的には16または32ですが、これは保証されません。 これは、GMP / MPIRの実装をユーザーが利用できないためです。 したがって、この関数を使用するには、四肢のサイズを推測する必要があり、プラットフォームによって異なる場合があります。







これを修正するために、PHP 5.6は関数gmp_random_bits()



およびgmp_random_range()



追加しました。これにより、使用する乱数の範囲を正確に制御できます。 これらの関数は、常にgmp_random()



よりも優先されるべきです。

gmp_random()



Deprecation notice



スローされます。







廃止された関数each()



each()



関数を使用して、 foreach



などの配列を反復処理できます。 各呼び出しで、現在のキーと値を含む配列を返し、内部配列のポインターを次の位置に進めます。 マニュアルに記載されている一般的な使用法は次のとおりです。







 reset($array); while (list($key, $val) = each($array)) { echo "$key => $val\n"; }
      
      





each



関数はforeach



ほとんどすべてでforeach



劣り、とりわけ10倍遅くなります。

この機能のサポートにより、一部の言語の変更で問題が発生します。 たとえば、無効な配列コンテナ( RFC )に関する警告では、 list()



を除外する必要がありました。 each



の一般的な使用はeach



警告なしで配列オフセットにfalse



アクセスできるという事実に依存しているためです。







現在、ほとんどの場合ループで使用されるため、 each



の最初の呼び出しで非Deprecation warning



スローされます。







非推奨の文字列引数を使用した()関数のアサート



assert()



関数には2つの操作モードがあります。文字列以外が渡された場合、値がtrueであることを確認します。 文字列が渡された場合、 eval()



を介して起動され、assertはeval()



結果の有効性をチェックします。







この動作の理由は、PHP 7より前では、これが式の評価を防ぐ唯一の方法であったためです。 PHP 7以降、iniファイルのzend.assertions



オプションを使用して、式の評価を回避できます。 したがって、文字列引数の暗黙的な計算をサポートする必要はなくなりました。







assert($value)



を使用assert($value)



を検証すると、 $value



文字列である可能性$value



高い場合にリモートコード実行の脆弱性が発生します。

assert()



文字列引数とともに使用された場合、非Deprecation notice



スローされるようになりました。







エラーハンドラの非推奨の$ errcontext引数



set_error_handler()



を使用して設定されたエラーハンドラは、 $errcontext



最後の引数として渡されます。 この引数は、エラーが生成された場所のすべてのローカル変数を含む配列です。







この関数は、 $errcontext



を使用して現在のスコープ内のすべての参照とオブジェクトを変更できるため、最適化が困難です。 この機能は実際には使用されません。 エラーの場所で状態変数を確認する場合は、デバッガーを使用する必要があります。







エラーコンテキストにはローカル変数のみが含まれていることに注意してください。 $this



および関数の引数を含むバックトレースエラーは、 debug_backtrace()



介して引き続き利用可能です。







この場合、 Deprecation warning



をスローすることは不可能であるため、この機能は単にドキュメントで非推奨としてマークされます。







非推奨の定数INTL_IDNA_VARIANT_2003



PHP 7.2では、定数INTL_IDNA_VARIANT_2003は非推奨です。

PHP 7.4では、 idn_to_ascii()



およびidn_to_utf8()



が変更され、デフォルトの$variant



パラメーターはINTL_IDNA_VARIANT_UTS46になります。

PHP 8.0では、INTL_IDNA_VARIANT_2003のサポートが削除されます。







キャスト(バイナリ)およびb ""リテラル( RFC )は非推奨です



(binary)



およびb



プレフィックスのサポートは、 PHP 6



との互換性のためにPHP 5.2.1



追加されましたが、このバージョンはまだ登場しておらず、バイナリ文字列を実装しようとする試みがこれ以上ないかは不明です。 ただし、これらは無視されますが、まだ言語スキャナーで受け入れられます。

これらのカーストを使用すると、 Deprecation notice



スローされるようになりました。







バージョン7.2専用に、5から始まるPHPバージョンの変更点を説明する「 PHPの新機能 」というリポジトリを用意しました。







あなたはソースで英語のリストを見つけることができます:

https://github.com/php/php-src/blob/PHP-7.2/UPGRADING

https://wiki.php.net/rfc#php_next_72







新しいバージョンをオンラインで試してください:

https://3v4l.org/







ご覧のとおり、グローバルな変更はほとんどありません。

PHPの変更についてどう思いますか? 最も気に入った機能はどれですか?








All Articles