PHPのお勉強!

PHP TOP

下位互換性のない変更点

エラーや例外の取り扱いの変更

fatal error や recoverable fatal error の多くが、PHP 7 では例外に変換されるようになりました。 これらの例外は Error クラスを継承したもので、 このクラスは Throwable インターフェイスを実装しています。 この新しいインターフェイスを、すべての例外が実装しています。

エラーではなく例外がスローされるようになるということは、自作のエラーハンドラは呼び出されなくなるということです (Error 例外をキャッチしなかった場合は、fatal エラーが発生します)。

PHP 7 におけるエラーハンドリングの詳細な説明は PHP 7 のエラー を参照ください。 この移行ガイドでは、下位互換性のない変更点を列挙するだけにとどめます。

set_exception_handler() が常に Exception オブジェクトを受け取るとは限らない

set_exception_handler() で登録した例外ハンドラの実装で Exception 型を宣言している場合は、 Error オブジェクトがスローされると fatal エラーが発生します。

PHP 5 と PHP 7 の両方で動くハンドラを書く場合は、ハンドラで型宣言をしてはいけません。 PHP 5 で動いていたコードを移行する際に、そのコードが PHP 7 でだけ動けばいいのなら、 Exception 型で宣言している部分を単純に Throwable 型に置換するだけでかまいません。

<?php
// PHP 5 でのこの実装は、そのままでは PHP 7 では動きません
function handler(Exception $e) { ... }
set_exception_handler('handler');

// PHP 5 と 7 の両方で動きます
function handler($e) { ... }

// PHP 7 でだけ動きます
function handler(Throwable $e) { ... }
?>

内部のコンストラクタは、失敗したときに常に例外をスローする

これまでは、コンストラクタの処理が失敗した際に、 null を返したり使用不能なオブジェクトを返したりする内部クラスがありました。 PHP 7 では、同様の場合に Exception をスローするようになりました。 ユーザー定義のクラスでは以前からそうすべきだとされていたことです。

パースエラーが発生すると ParseError をスローする

パースエラーが発生すると ParseError オブジェクトをスローするようになりました。 eval() のエラーハンドリングをする際には、catch ブロックを用意してこのエラーを処理しなければいけません。

E_STRICT 通知の深刻度の変更

すべての E_STRICT 通知が、改めて別のレベルに移動しました。 定数 E_STRICT はそのまま残っているので、 error_reporting(E_ALL|E_STRICT) のような呼び出しがエラーになることはありません。

E_STRICT 通知の深刻度の変更
状況 新しいレベル / 挙動
Indexing by a resource E_NOTICE
Abstract static methods 通知は削除され、エラーにはならない
"Redefining" a constructor 通知は削除され、エラーにはならない
Signature mismatch during inheritance E_WARNING
Same (compatible) property in two used traits 通知は削除され、エラーにはならない
Accessing static property non-statically E_NOTICE
Only variables should be assigned by reference E_NOTICE
Only variables should be passed by reference E_NOTICE
Calling non-static methods statically E_DEPRECATED

変数の取り扱いの変更

PHP 7 では、抽象構文木を使ってソースファイルをパースするようになりました。 そのおかげで言語としてのさまざまな改良ができるようになりました。 これまでの PHP が使っていたパーサーでは不可能だったこともできるようになったからです。 しかしその結果、一貫性を保つために一部の機能を削除することになりました。 これは、下位互換性を損ねるものです。 このセクションでは、それらについて説明します。

変数やプロパティ、メソッドへの間接的なアクセスの扱いの変更

変数やプロパティそしてメソッドへの間接的なアクセスを、厳密に左から右の順で評価するようになりました。 以前のバージョンでは、場合によって評価の順が逆転することもありました。 評価順の変更を、以下の表にまとめます。

間接的なアクセスの評価順の変更
PHP 5 での解釈 PHP 7 での解釈
$$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']()

今までのバージョンにおける右から左の評価を想定しているコードは、 波括弧を使って評価順を明示するように (表の中央列のように) 書き直す必要があります。 そうすれば、PHP 7.x との互換性を保ちつつ、PHP 5.x との下位互換性も維持できます。

これは、global キーワードにも影響します。 必要であれば、波括弧構文を使えばこれまでのバージョンでの挙動を再現できます。

<?php
function f() {
// PHP 5 でしか使えません
global $$foo->bar;

// PHP 5 と PHP 7 の両方で使えます
global ${$foo->bar};
}
?>

list() の取り扱いの変更

list() での変数の代入が、逆順ではなくなる

list() における変数への代入が定義された順番どおりに行われるようになりました。 今までのように逆順にはなりません。 この変更の影響を受けるのは、list()[] 演算子と組み合わせて使うときくらいでしょう。その例を示します。

<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>

上の例の PHP 5 での出力は、このようになります。

array(3) {
  [0]=>
  int(3)
  [1]=>
  int(2)
  [2]=>
  int(1)
}

上の例の PHP 7 での出力は、このようになります。

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

一般論として、 list() での代入がどの順で行われるかに依存するコードは書かないことを推奨します。 代入の順番は、実装の都合によって今後も変わる可能性があるからです。

空の list() の廃止

空の list() を作ることはできなくなりました。 次のようなコードは PHP 7 では使えません。

<?php
list() = $a;
list(,,) =
$a;
list(
$x, list(), $y) = $a;
?>
list() は文字列を展開しない

list() は文字列変数を展開できなくなりました。 かわりに str_split() を使いましょう。

参照による代入で自動的に作成した配列要素の並び順の変更

参照による代入で配列の要素を自動的に作成した場合の、 要素の並び順が変更されました。 以下に例を示します。

<?php
$array
= [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>

上の例の PHP 5 での出力は、このようになります。

array(2) {
  ["b"]=>
  &int(1)
  ["a"]=>
  &int(1)
}

上の例の PHP 7 での出力は、このようになります。

array(2) {
  ["a"]=>
  &int(1)
  ["b"]=>
  &int(1)
}

関数のパラメータを括弧で囲んでもその振る舞いは変わらない

PHP 5 では、関数のパラメータを冗長な括弧で囲んでおくと、 関数のパラメータを参照渡しにした場合の警告を抑止することができました。 PHP 7 では、たとえ括弧で囲んでも警告が常に発生します。

<?php
function getArray() {
return [
1, 2, 3];
}

function
squareArray(array &$a) {
foreach (
$a as &$v) {
$v **= 2;
}
}

// PHP 7 では警告が発生します
squareArray((getArray()));
?>

上の例の出力は以下となります。

Notice: Only variables should be passed by reference in /tmp/test.php on line 13

foreach の変更

foreach の振る舞いが多少変わりました。 主に、内部の配列ポインタの扱いや、反復処理中の配列の変更に関する部分です。

foreach は内部の配列ポインタを変更しない

PHP 7 より前のバージョンでは、foreach で配列を反復処理する際に、内部の配列ポインタを変更していました。 PHP 7 ではそのようにはならず、以下の例のようになります。