最近仕事のメモを取るのに、日付ベースでノートを保存出来る wri.pe というサービスを使い始めた YamaYuski です。
弊社はPHPに強い会社と自負していますが、これまで社内勉強会では PHP 7 について詳しく取り上げていませんでした。(もちろん社内プロジェクトで使えるかどうかのチェックなどはしています)
これではいかんということで、社内でもPHP7の新機能や注意点をRFCベースで共有し、今後のアップデートに備えるべく、筆を取りました。
その結果、 重量級 な内容となってしまいましたよ。
スライドにして106枚。
(何故こんな枚数になった。)
ということで、折角作ったのに社内にしか公開しないのはもったいない、ということで、ひとまとめにした内容を記事として書き起こしてみます。
※今回はmarkdownを使って資料を書いたので、スライドではなく文章そのままにしてみました!
※RFCのタイトルのリンクで、元のwikiに飛べます! 英語が読める方はそちらもご覧ください!
RFC とは
Request for Comments の略で、仕様を公募しパブリックな場所で議論した上で、投票で実装するかどうかを決めるというプロセスをPHPは採用しています。
https://wiki.php.net/rfc ここに5.3以降の全てのRFCが載っています。
詳しく説明するRFC
- Throwable インターフェースの導入
- 文脈に沿った解析
- 無名クラス
- 結合比較演算子
- 戻り値の型宣言
- Null 合体演算子
- Expectations
- スカラー型宣言
1. Throwable インターフェースの導入
Throwable
というインターフェースを新設し、致命的なエラーですらキャッチ出来るようになりました。
致命的ではないエラー(未定義変数/定数の参照など)は、今まで通り trigger_error
がなされ、処理は継続します。
PHP5までのExceptionツリー
- Exception : 全ての例外の基底クラスです
- ErrorException extends Exception :
set_error_handler
などで変換後の例外クラスです
- ErrorException extends Exception :
PHP7のExceptionツリー
- interface Throwable :
throw
ステートメントを利用して投げられるオブジェクト - Exception implements Throwable : 通常の例外
- Error implements Throwable : PHP内部エラー
- ArithmeticError extends Error : 数学的な操作によるエラー
- AssertionError extends Error :
assert()
によるアサーションが失敗した場合に起こるエラー - TypeError extends Error : タイプヒントと異なる型を関数に渡した場合に起こるエラー
- ParseError extends Error : 構文解析時(=eval時)に起こるエラー
アプリコードレベルの影響
基本ツリーは変わりましたが、アプリコードは基本的に何も変えることがありません。
<?php try { $divide_by_zero = 100 / 0; } catch (Exception $e) { // 通常通りキャッチされず致命的エラーを吐いて終了します }
しかし、PHPUnitなどのライブラリ内部やフレームワーク内で利用されることで、
<?php try { executeTestCode(); } catch (Exception $exception) { // 例外がスローされた時の処理を行います throwedException($exception); } catch (Error $error) { // 致命的エラーがスローされた時の処理を行います(新設!) throwedError($error); }
といった形で、テスト中に致命的エラーが発生しても処理を継続することが出来るようになります。
※ただし、 Throwable
Error
TypeError
ParseError
などのクラスが定義されたため、既存アプリコードで同名クラスを実装している場合はクラス名を変更する必要があります。
2. 文脈に沿った解析
PHPは現在 64 の予約語が存在します。現状ではその予約語をそのまま変数名としたり、メソッド名にすることは構文エラーとなり出来ません。
しかし、それでは適正でない名前でユーザーサイドAPIの実装をしなければならないということでもあります。
そこで、PHP7では、構文解析を文脈に沿って行うことにより、この予約語の利用制限を取り払いました。
文脈に沿った解析
<?php // <= PHP5 class Collection { public function forEach(callable $callback) { /* */ } public function list() { /* */ } } // throws: PHP Parse error: Syntax error, unexpected T_FOREACH, expecting T_STRING on line 2 // throws: PHP Parse error: Syntax error, unexpected T_LIST, expecting T_STRING on line 3 // PHP7ではこの実装が可能になります(for, and, listは予約語)。 $projects = Finder::for('project')->and('priority', '>', 9)->list($limit, $offset);
注意
<?php // これだけはどうしても出来ません class Foo { const class = 'Foo'; } // Fatal error: Cannot redefine class constant Foo::CLASS as it is reserved in %s on line %d
現在の予約語
callable class trait extends implements static abstract final public protected private const enddeclare endfor endforeach endif endwhile and global goto instanceof insteadof interface namespace new or xor try use var exit list clone include include_once throw array print echo require require_once return else elseif default break continue switch yield function if endswitch finally for foreach declare case do while as catch die self parent
※多いですね
3. 無名クラス
ドキュメントが不要で、実行時に一度しか呼ばれないような一時的なクラスの場合、クラスに名称をつけずに宣言することが可能になります。
ユースケース
1. テスト時のモッククラスの作成をテストメソッド中に簡単に行える
<?php function testCase() { $mock = new class extends MockClass { protected function toBeMocked() { return true; } }; // toBeTested内で toBeMocked が呼ばれている $result = $mock->toBeTested(); // ... }
2. ネストクラスのようなスコープを利用出来る
<?php class Outside { protected $data; public function __construct($data) { $this->data = $data; } public function getArrayAccess() { return new class($this->data) extends Outside implements ArrayAccess { public function offsetGet($offset) { return $this->data[$offset]; } public function offsetSet($offset, $data) { return ($this->data[$offset] = $data); } public function offsetUnset($offset) { unset($this->data[$offset]); } public function offsetExists($offset) { return isset($this->data[$offset]); } }; } }
3. ささいな実装のためにautoloaderに負担をかけない
といったことが想定されています。
4. 結合比較(スペースシップ)演算子
< =>
という比較演算子が追加されます。これは Perl や Ruby で既に実装されているもので、左辺と右辺を比較した結果を -1
0
1
のどれかで返します。
<?php // だいたいこれと同じ(細かくは違うけど) function compare($a, $b) { if ($a < $b) { return -1; } elseif ($a > $b) { return 1; } else { return 0; } } compare(1, 2); // -1 1 <=> 2; // -1
<?php // Integers echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // Floats echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // Strings echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 echo "a" <=> "aa"; // -1 echo "zz" <=> "aa"; // 1
これは usort()
などのソートを行う際に非常に有用で、
<?php // 結合比較演算子がない場合 function order_func($a, $b) { return ($a < $b) ? -1 : ($a > $b ? 1 : 0); } // 結合比較演算子がある場合 function order_func($a, $b) { return $a <=> $b; }
非常にシンプルかつ的確な比較を表すことが可能になります。
逆に言うと、ソート以外ではあまり活用されない方が良いかもしれません。
5. 戻り値の型宣言
(※Return type は 戻り値 返り値 など日本語では表記揺れがありますが、ここでは 戻り値 とします)
関数やメソッドの戻り値の型を指定することが出来るようになります(もちろん指定しないことも可能)。
戻り値の型宣言
戻り値型を宣言出来ることによるメリットには次のようなものが上げられています。
- インターフェースなどの親クラスが予期していない戻り値を子クラスが返してしまうことを防ぐ
- 意図していない戻り値を防ぐ
- コメントと違い、簡単に無効化出来ない方法で戻り値の情報をドキュメント化する
構文
シンタックスは非常に単純です。
<?php function foo(): array { return []; }
この関数が array 以外を返した場合、 TypeError が出ます。
戻り値を宣言しない場合は、今まで通りの挙動が行われます。
不一致・署名バリデーション
継承の中で、戻り値の定義は常に不変です。つまり、子クラスが親メソッドをオーバーライドする場合は、子メソッドは親と完全に同じ戻り値の型を持たなければなりません。
親クラスが戻り値型を宣言していない場合は、子クラスが自由に宣言可能です。
共変性(Covariant)のある型宣言は他の多数の言語で利用されていますが、いくつかの問題があったため取りやめられました。
以下は正しい継承です。
interface A { static function make(): A; } class B implements A { static function make(): A { return new B(); } }
以下の継承はエラーになります。
<?php interface A { static function make(): A; } class B implements A { static function make(): B { // 親と完全に一致しなければならないのでエラーになります return new B(); } }
型宣言の位置
戻り値の型情報を置く場所は、多言語では2つのメジャーなものがあります:
- 関数名の前
- 引数リストの閉じカッコの後
function foo
という形で「foo関数の実装位置を探す」といったことがよく求められていて(マジデ?)、パーサの変更も不要だったため後者が選ばれました。
戻り値に NULL を許可しない
<?php function foo(): DateTime { return null; // ダメ }
DateTime
と型宣言したにも関わらず null
を返してはいけません。
- 引数の挙動に合わせるため。引数に型宣言がある場合は、
null
は許可されない(null
デフォルト値が定義されている場合を除く)。 - デフォルトで
null
を許可することは型宣言の意義に反するため。
6. Null 合体演算子
<?php $key = isset($input['key']) ? $input['key'] : 'default';
という 値があるならそれを使い、ない場合はデフォルト値を入れる という処理はPHP内で良く使われていると思います。
<?php $key = $input['key'] ?: 'default';
という形で ?:
演算子は利用可能ですが、配列で該当のキーがない場合は E_NOTICE
が発生してしまいます。
そこで、 ??
という演算子が設けられました。
Null合体演算子
Wikipediaを見るとわかりますが、C#, Perl, Swift, SQLなどですでに実装されています。
PythonやJavascriptでも似たようなものが実装されていますが、これは厳密な比較ではないので注意が必要です。
利用方法
<?php $username = $_GET['user'] ?? 'nobody'; // 次と同一 : $username = isset($_GET['user']) ? $_GET['user'] : 'nobody'; $model = Model::get($id) ?? $default_model; // 次と同一 : if ( ($model = Model::get($id)) === NULL) { $model = $default_model; } // チェーンも可能 $x = ["yarr" => "meaningful_value"]; var_dump($x["aharr"] ?? $x["waharr"] ?? $x["yarr"]); // string(16) "meaningful_value" function foo() { echo "executed!", PHP_EOL; } var_dump(true ?? foo()); // 短絡評価なので foo() は実行されない
7. Expectations
これまでのPHPにも bool assert(mixed $assertion [, string $description])
というアサーション関数がありましたが、
- 関数なので式を渡すことが出来ない
- 運用環境でも実行時に必ずオーバーヘッドが存在する
といった重要な課題があり、あまり利用されていませんでした。
PHP7では関数ではなく言語仕様として生まれ変わり、より使いやすい仕組みとなりました。
iniの設定によって、そもそも assert
のopcodeを生成しないようにすることも可能になりました。
<?php if ($i % 3 == 1) { // ... } else if ($i % 3 == 2) { // ... } else { // ここは ($i % 3 == 3) // ... }
こんなコメント書きますよね。だけども、コメントはソースコードを読まない限り分かりません。
<?php if ($i % 3 == 1) { // ... } else if ($i % 3 == 2) { // ... } else { // 実際は ($i % 3 == 0) assert($i % 3 == 3); }
こう書けば、実行時にエラーが出て分岐が間違っていることに気づくことが出来ます。
こういった「コードが正しいことを 期待する 」ために assertion が利用出来ます。
これを Expectation と言うらしいです(詳しくはわからず)。
<?php // よくやるけどなんかわかりづらい public function setResponseCode(int $code) { if (510 < $code or 100 > $code) { throw new LogicException('渡されたコードが異常です code=' . $code); } $this->code = $code; } // 引数が正しいことを「期待する」書き方 public function setResponseCode(int $code) { assert(100 <= $code and 510 >= $code, '渡されたコードが異常です code=' . $code); $this->code = $code; }
expectationを使うと、開発中は詳細にチェックしプログラマーにミスを起こさせない状態にし、本番では assertion を無効にすることで速度を向上させられます。
ミスを起こさせない
ここ重要。
※DB値とかリクエストのバリデーションにassertionを使ってしまうと、本番でガンスルーされるので気をつけよう
8. スカラー型宣言
要するに
<?php function yourName(string $name) { echo "Hello, {$name}."; } function yourAge(int $age) { echo "Age : {$age}"; }
タイプヒントに int
, float
, string
, bool
を利用出来るようになります。
先ほど紹介した 戻り値の型宣言 にも利用可能。
<?php function multiply(int $a, int $b): int { return $a * $b; }
ということで、 int
, float
, string
, bool
は予約文字列となり、クラス名などで利用出来なくなりました。
結構使ってるライブラリが多そうな所ですね。
基本的に宣言するものは「緩い型」となります(比較する時の ==
これ)。
暗黙の型変換を行わない宣言をするには
declare(strict_types=1);
という謎のディレクティブを書く必要があります。
ディレクティブをファイルの先頭に書いたファイル内のタイプヒント実行は全て厳密になります。
これは関数に紐付けられるものではなく、 ファイルに紐付けられる ということです。
(foo.php) <?php declare(strict_types=1); function foo(): int { return 0.0; }
(bar.php) <?php include "foo.php"; foo(); // 問題なし
(baz.php) <?php declare(strict_types=1); include "foo.php"; foo(); // TypeError
暗黙型変換では、結構うまいことやってくれます
<?php function add(float $a, float $b): float { return $a + $b; } add(5, 10); // 大丈夫 int -> float add("5", "10"); // 大丈夫 数値のあるstring -> float add("a", 5); // ダメ 数値のないstring -> float
その他細かいこと
int?
(nullも可能) やint|float
(どっちか) のような記述は、影響範囲が大きくなりすぎるため省略numeric
(=int|float) はfloat
とかけばint
も受け付けるので実装しない- 内部関数は戻り値のタイプヒントを行わない(エラーでnullを返すことがあるので)
- RFCへの投票が108人賛成(166人中)だった(他のは20人とか)
その他のRFC
そこまで重要ではない、シンプルなRFCです。
ただ、既存コードに影響する可能性があるものも含まれるので、それぞれにおいては注意しましょう。
9. 暗号論的擬似乱数生成器のユーザ利用
暗号論的擬似乱数生成器(=つまり強い乱数)を簡単に利用するため、 random_bytes
及び random_int
関数が実装されます。
10. 例外を投げるランダム関数
random_int
random_bytes
の処理に失敗($min > $max, 引数異常等)した場合、nullではなく例外を投げるようにして、セキュリティ部分でバグを見逃さないようにします。
11. preg_replace_callback_array
関数の追加
preg_replace に ‘/e’ modifier を利用出来なくなったので、代わりに正規表現をキーに、コールバックを値とした配列を渡せる preg_replace_callback_array
が実装されます。
12. ジェネレータのデリゲーション
yield from
構文を用いることで、ジェネレータの中でさらに複数のジェネレータを利用することが出来るようになります。
13. 型の予約語の追加
int
string
などのスカラー型のクラス・インターフェース・トレイトの宣言を禁止します。
14. 内部クラスのコンストラクタの振る舞い変更
PDO、finfo、MessageFormatterなどの内部クラスのコンストラクタで処理に失敗した場合、例外ではなくnullが返ります。
15. E_STRICTの区分変更
E_STRICTカテゴリを削除し、既存のものはE_DEPRECATEDやE_NOTICE, E_WARNINGに変更します。
16. PHP4コンストラクタの削除
クラス名で宣言するタイプのコンストラクタを E_DEPRECATED として処理します。
<?php class Filter { // こんなの function filter($a) {} }
17. date.timezoneの警告を削除
date.timezoneを指定しなかった場合に E_WARNING が発生していましたが、今後は発生せずデフォルトの UTC を利用します。
18. foreachの挙動修正
特殊な foreach
の操作(リファレンス渡し、ループ中の current
unset
利用など)の挙動を正しいものに修正します。
19. 利用できないSAPIの削除
長い間利用不能だったりサポートが受けられていなかったりするSAPIを削除します。
aolserver, apache, apache_hooks, caudium, continuity, isapi, milter, phttpd, pi3web, roxen, thttpd, tux, webjames, apache2filter, nsapi, interbase, mssql, oci8, pdo_oci, sybase_ct, mysql, ereg
20. 現在のjson拡張をjsondに置き換え
現在のJSON拡張はフリーライセンスではなく、ディストリビューションでの配布に問題があったため、PECLのjsond拡張に置き換えます。
21. jsonエンコード時に少数部分を保持する
10.0などの値をエンコードした場合、デコードすると (int)10 となってしまうことを防ぐオプション JSON_PRESERVE_ZERO_FRACTION
を追加します。
22. より早い引数パースAPI
is_string
や ord
などのシンプルな関数でオーバーヘッドが大きい引数のパース部分を改善したAPIを提供します。
WordPressで5%弱のパフォーマンスアップ
23. Unicodeのコードポイントエスケープ構文
echo "\u{202E}Reversed text";
といった構文で、Unicodeのコードポイント(符号位置)を指定して文字列を参照出来るようになります。
24. ネイティブTLS
TLS(Thread Local Storage)を改善します(PHP内部のみ影響)。
25. Integer セマンティクス
intの扱いをクラスプラットフォームで一貫性を持つようにします。
26. オーバーフロー時ZPPを失敗させる
integer
が予期される場所に float
型をオーバーする値や、NaNが渡された場合に失敗するようになります。
27. phpngブランチをmasterブランチにマージ
phpngと呼ばれていたメモリ使用の最適化コードをmasterブランチにマージします。
アプリコード上の変更は不要ですが、CPU使用率・メモリ使用率ともに大幅に改善されています
詳細は https://wiki.php.net/phpng こちら。
28. 抽象構文木
コンパイル時に一度抽象構文木を作成するようにします。
- パーサとコンパイラのメンテナンスがしやすくなる
- 構文の決定を技術的な問題から切り離す
for
文などのループでは若干の速度向上が見込まれますが、コンパイル時のメモリ使用率が数%上昇する可能性が有ります。
もちろん、 opcode cache を利用していればメモリ使用率は変化しません。
29. 変数構文の均一化
内部的に矛盾のない完璧な変数構文を導入します。
<?php $foo()['bar']() [$obj1, $obj2][0]->prop getStr(){0} // ネストした :: $foo['bar']::$baz $foo::$bar::$baz $foo->bar()::baz() // ネストした () foo()() $foo->bar()() Foo::bar()() $foo()() // 任意表現 (...) に対しての操作 (...)['foo'] (...)->foo (...)->foo() (...)::$foo (...)::foo() (...)() // こういったものも可能 (function() { ... })() ($obj->closure)() // デリファレンス可能なスカラ型への操作(便利ではない) "string"->toLower() [$obj, 'method']() 'Foo'::$bar
以下の構文は挙動が変化するため注意
// 今までの意味 // 新しい意味 $$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz'] $foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz'] $foo->$bar['baz']() $foo->{$bar['baz']}() ($foo->$bar)['baz']() Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']()
30. 内部変数(文字列長、整数)の64bitプラットフォーム向け改善
大きなファイルや64bit整数の操作などのプラットフォーム間の一貫性を向上させるため、いくつかの内部変数の型を修正します。
31. Closure::call
現在のPHPの Closure
は、バインドを実行した場合新しいクロージャを都度生成します。
そのオーバーヘッドを減らすため、 call
メソッドが追加されます。
<?php $a = function () { return $this->x; }; class FooBar { private $x = 3; } $foobar = new FooBar; // 今まで for ($i = 0; $i < 1000000; $i++) { // 新しいインスタンスが生成されるのでオーバーヘッドがある $x = $a->bindTo($foobar, "FooBar"); $x(); } // これから for ($i = 0; $i < 1000000; $i++) { // オーバーヘッドがない(別のバインドを行って実行することも可能 $a->call($foobar); }
32. list() の振る舞いの矛盾を修正
文字列に対しても list()
関数によりアンパック出来た場合がありましたが、出来ないように修正されます。
$ php -r 'list($a,$b) = "aa";var_dump($a,$b);' NULL NULL $ php -r '$a[0]="ab"; list($a,$b) = $a[0]; var_dump($a,$b);' string(1) "a" string(1) "b"
33. 代替PHPタグを削除
- 特別な利用法がない
- ASPタグはiniの設定に依存するため、ポータブルではない
- ASPタグが underscore.js のテンプレートをクラッシュさせる
- 異なる開始・終了タグの組み合わせが出来るため、混乱させられる
などの理由から、以下のPHP開始・終了タグが削除されます。
<% <%= %> <script language="php"> </script>
既にこのタグが利用されている場合は、 変換スクリプト により変換出来ます。
34. switch 中で複数の default ケースを記述した際に構文エラーとする
現在、 switch 中に複数の default ケースを記述した場合は、最後に記述したもののみ実行されますが、仕様と異なる振る舞いのため、コンパイルエラーとなります。
35. “call to a member function of a non-object” をキャッチ可能にする
こちらは Throwable インターフェースの導入 に統合されました。
36. フィルタされた unserialize()
シリアライズされたデータが外部で不正に書き換えられた場合、アンシリアライズすることでセキュリティに問題が出ます。
そこで、オブジェクトを許可しない、指定したクラスのみシリアライズする、というオプションを追加します。
<?php // 今まで通り全てアンシリアライズします $data = unserialize($foo); // 全てのオブジェクトを __PHP_Incomplete_Class に変換します $data = unserialize($foo, ["allowed_classes" => false]); // MyClass, MyClass2 以外のオブジェクトを __PHP_Incomplete_Class に変換します $data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]); // デフォルトと同様です $data = unserialize($foo, ["allowed_classes" => true]);
37. ICU IntlChar クラス
ローカライズに便利な ICU 周りのメソッドを追加します。
38. session_start() にINI設定引数を追加
session_start()
関数にiniの設定を連想配列で渡して上書き出来るようになりました。
また、 read_and_close
オプションを指定すると、セッション情報読み込み後すぐにクローズするため、セッションを書き換えない場合に意図しないロックを防ぐことが出来ます。
lazy_write
というオプションも追加され、指定することで書き込みがなかった場合にストレージへ書き込み処理を行わないことによってパフォーマンスを向上させられます。
※この設定を変更した場合、同一クライアントからの同時接続時に最後に書き込まれるセッション値が変わる(最後にセッションに書き込んだリクエスト
から 最後にセッションを修正したリクエスト
へ)ので注意が必要です。
39. 数値の文字列でHEXのサポートを削除
数値文字列のHEX対応は場所によって振る舞いの一貫性がないため、削除されます。
// HEX非対応 var_dump((int) "0x123"); // int(0) var_dump((float) "0x123"); // float(0) // HEX対応 var_dump(is_numeric("0x123")); // true var_dump('0x123' == '291'); // true
0x123
のように文字列ではなく数値として表現している場合は影響されません。
40. Use宣言のグルーピング
同一ネームスペースからの use
の冗長な記述を、グルーピングして簡略化出来るようになります。
use const
use function
にも適用可能。
<?php // 今まで use Doctrine\Common\Collections\Expr\Comparison; use Doctrine\Common\Collections\Expr\Value; use Doctrine\Common\Collections\Expr\CompositeExpression; // これから use Doctrine\Common\Collections\Expr\{ Comparison, Value as v, // asも使える CompositeExpression };
41. エンジン内の例外
こちらは Throwable インターフェースの導入 に統合されました。
42. ジェネレータ内でのreturn
ジェネレータ内で return
を利用可能にします。
43. 切断後も出力バッファを保持する
ユーザがコネクションを切断した後も出力バッファを維持し、利用し続けられる状態にします。
44. intdiv()
(int)(3 / 2)
というハックっぽいint値の割り算を、関数として実行出来るようにします。
<?php var_dump(intdiv(5, 2)); // int(2)
45. カスタムセッションハンドラの戻り値バグ修正
falseを返しても成功になり、trueを返すと成功でも失敗でもない状態だったので修正します。
46. gc_collect_cyclesを関数ポインタにする
プロファイラがガベージコレクションのタイミングを把握出来るようにするため、
gc_collect_cycles
を関数ポインタにします。
PHP7.1 用に実装済みのRFC
オマケとして、PHP7.1で実装済みのRFCもここで紹介してしまいます。
正しくない数値文字列を警告する
異常な数値文字列を数学系の演算子で利用した場合にエラーを送出します。
<?php $numberOfApples = "10 apples" + "5 pears"; // Notice: A non well formed numeric string encountered in example.php on line 3 // Notice: A non well formed numeric string encountered in example.php on line 3
list()のキーを指定可能にする
連想配列を変数に展開する際に便利になるキー指定を追加します。
class ElePHPant { private $name, $colour, $age, $cuteness; public function __construct(array $attributes) { list( "name" => $this->name, "colour" => $this->colour, "age" => $this->age, "cuteness" => $this->cuteness ) = $attributes; } // ... }
マイナスの文字列オフセット指定を一般化する
文字列系関数などでのオフセット指定時にマイナスを入れられるようにします。
OpenSSL AEADサポート
openssl_decrypt
openssl_encrypt
に AEAD 暗号化モードのサポートを追加します。
Void戻り値型
戻り値を持たないメソッドに void 型を指定出来るようになります。
function a(): void { // ok } function b(): void { return; // ok } function c(): void { // Fatal error: A void function must not return a value return null; }
クラス定数のvisibilityを変更出来る
private const
などが出来るようになり、重要度の表現や不用意な定数変更によるリグレッションを防ぎます。
HTTP/2 サーバプッシュサポート
ext/curl にHTTP/2のプッシュ機能を追加します。
それでは、良いPHP7ライフを。