インフィニットループ 技術ブログ

2016年04月14日 (木)

著者 : m-yamagishi

【スライドにして106枚】PHP7.0 全46RFCの概要紹介

最近仕事のメモを取るのに、日付ベースでノートを保存出来る wri.pe というサービスを使い始めた YamaYuski です。
php7
弊社はPHPに強い会社と自負していますが、これまで社内勉強会では PHP 7 について詳しく取り上げていませんでした。(もちろん社内プロジェクトで使えるかどうかのチェックなどはしています)
これではいかんということで、社内でもPHP7の新機能や注意点をRFCベースで共有し、今後のアップデートに備えるべく、筆を取りました。
その結果、 重量級 な内容となってしまいましたよ。
スライドにして106枚。
(何故こんな枚数になった。)
ということで、折角作ったのに社内にしか公開しないのはもったいない、ということで、ひとまとめにした内容を記事として書き起こしてみます。
※今回はmarkdownを使って資料を書いたので、スライドではなく文章そのままにしてみました!
※RFCのタイトルのリンクで、元のwikiに飛べます! 英語が読める方はそちらもご覧ください!

RFC とは

Request for Comments の略で、仕様を公募しパブリックな場所で議論した上で、投票で実装するかどうかを決めるというプロセスをPHPは採用しています。
https://wiki.php.net/rfc ここに5.3以降の全てのRFCが載っています。

詳しく説明するRFC

  1. Throwable インターフェースの導入
  2. 文脈に沿った解析
  3. 無名クラス
  4. 結合比較演算子
  5. 戻り値の型宣言
  6. Null 合体演算子
  7. Expectations
  8. スカラー型宣言

1. Throwable インターフェースの導入

Throwable というインターフェースを新設し、致命的なエラーですらキャッチ出来るようになりました。
致命的ではないエラー(未定義変数/定数の参照など)は、今まで通り trigger_error がなされ、処理は継続します。

PHP5までのExceptionツリー

PHP7のExceptionツリー

アプリコードレベルの影響

基本ツリーは変わりましたが、アプリコードは基本的に何も変えることがありません。

<?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. 結合比較(スペースシップ)演算子

< => という比較演算子が追加されます。これは PerlRuby で既に実装されているもので、左辺と右辺を比較した結果を -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 を返してはいけません。

  1. 引数の挙動に合わせるため。引数に型宣言がある場合は、 null は許可されない(null デフォルト値が定義されている場合を除く)。
  2. デフォルトで null を許可することは型宣言の意義に反するため。

6. Null 合体演算子

Null合体演算子 – Wikipedia

<?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_stringord などのシンプルな関数でオーバーヘッドが大きい引数のパース部分を改善した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タグを削除

などの理由から、以下の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ライフを。

ブログ記事検索

このブログについて

このブログは、札幌市・仙台市の「株式会社インフィニットループ」が運営する技術ブログです。 お仕事で使えるITネタを社員たちが発信します!