導入
煽りタイトルすいません.PHP 7 のエラーや標準例外について,違いを整理し,使い分けを考察する記事です.
【引用】 PHP 7.0.0α2 の例外の例外の継承関係を可視化してみた by @ngyuki
すべてを捕捉対象にする Throwable
Throwable
は, PHP 7 の throw
文でスロー可能なあらゆるオブジェクトが実装する基底インターフェイスです. Error
および Exception
はこれを実装しています.但し,PHPコードとして書かれるクラスが Throwable
インターフェイスを直接実装することはできません.
とりあえず catch
句に Throwable
と書いておけば,そのブロック内でスローされた Error
と Exception
を捕捉できることが保証されます.
try {
...
} catch (\Throwable $e) {
...
}
但し, Error
を捕捉する必要性があるのは,**「フレームワークを自作していて,エラー時にもHTMLレンダリングを可能な限り行いたい」**など,極めて限定的な場合です.もしリソースの解放などを確実に行いたい場合には finally
句を使うのが正解です.
try {
...
} catch (\Throwable $e) {
unlink('/tmp/tmp.txt');
throw $e;
}
try {
...
} finally {
unlink('/tmp/tmp.txt');
}
エラー / Exception
/ Error
/ ErrorException
以上4点の違いや使い分けについて言及します.
旧来のエラー
PHPには主に以下のようなエラーがあります. (これで全てではありません)
E_PARSE (別名: Parse Error, Syntax Error, 文法エラー)
コードが文法的に誤っているときに発生します.一切の処理を行いません.
E_ERROR (別名: Fatal Error, 致命的なエラー)
処理を継続することが不可能になってしまった場合に発生します.発生したところで処理を停止します.これが発生するリスクを持つコードを書いてはいけません.
E_WARNING (別名: Warning, 警告)
処理を継続することは可能ですが,想定外の問題が起こったときに発生します.これが発生するリスクを持つコードは可能な限り書かないでおくべきです.
E_NOTICE (別名: Notice, 通知)
処理を継続することは可能ですが,想定内の問題が起こったときに発生します.これは手を抜いて無視する人と丁寧に対応する人に二分されますが,対応の仕方を知らないまま手抜きをするようなプログラマになってはならないと私は考えるので,ここでは徹底的に対応することにします.
このようなエラーは,PHP処理系内部で発生します.困ったことに,後述する特殊な変換処理を設定しないかぎりは,catch 句で捕捉することができません.**「旧来のエラー」は Throwable
ではありません.**本来ならば全てのエラーは Throwable
のもとに体系化されるべきなのですが,これは例外が実装されていなかった時代の名残です.
PHP処理系が持つ標準関数との互換性を強く意識したPHPコードでは,「旧来のエラー」を trigger_error
関数を用いてPHPレベルで能動的に発生させることもあります.
Exception
Error
や Throwable
が実装される前の PHP 5 時代には, Throwable
の代わりにすべての頂点にいたクラスです. Throwable
の実装には Error
と Exception
の2種類がありますが,能動的にスローする際には,普通のPHPコードとして書かれるものはすべて Exception
あるいはその継承クラスを使うべきです.
Error
PHP 7 から新設されたクラスです. Error
というクラス名になっていますが,「旧来のエラー」とは取り扱いが全く異なるものです. Exception
とは対極に, PHP処理系内部あるいはPHP処理系が持つ標準関数との互換性を強く意識したPHPコードで用いられます. PHP 7 以降は trigger_error
関数との使い分けに悩む気もしますが, PHP 5 時代の実装のバックポートには trigger_error
関数が, PHP 7 時代の実装のバックポートには Error
が使われるでしょう.
ErrorException
set_error_handler
関数と併用して,先述の「特殊な変換処理」で変換するためだけに存在するクラスです.非常に名前がややこしいですが, ErrorException
はあくまで Exception
の一部であって, PHP 7 から新設された Error
とは無関係です. ErrorException
は**「旧来のエラーから変換される Exception
」**という意味です.
【引用】 set_error_handler
と ErrorException
を組み合わせると幸せになるかも
set_error_handler(function($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
但し,ここで設定したハンドラは Fatal Error を受け取ることができず,どうしてもそれに対処したい場合は [`register_shutdown_function`] を使って「最後の悪あがき」をする程度しか方法がありません.
```php:
register_shutdown_function(function () {
$error = error_get_last();
if (!$error || !($error['type'] & (E_ERROR | E_PARSE | E_USER_ERROR | E_RECOVERABLE_ERROR))) {
return;
}
/* 最後の悪あがきをする */
});
**※ E_RECOVERABLE_ERROR
(別名 Catchable Fatal Error) は ErrorException
に変換可能な E_ERROR
相当のもので, set_error_handler
での設定が無い場合には E_ERROR
と同様の扱いになります.**PHP 5.2 から一部の E_ERROR
が E_RECOVERABLE_ERROR
に変更されています.
※ PHP 7 では E_WARNING
E_ERROR
E_RECOVERABLE_ERROR
E_PARSE
の一部が Error
に変更されています.
要約すると…
set_error_handler
なしの場合
- そのまま続行可能な旧来のエラー
→E_NOTICE
E_WARNING
E_USER_NOTICE
E_USER_WARNING
- 実行が停止する旧来のエラー
→E_ERROR
E_PARSE
E_RECOVERABLE_ERROR
E_USER_ERROR
-
catch
句で捕捉できるもの
→Error
Exception
set_error_handler
ありの場合
- 実行が停止する旧来のエラー
→E_ERROR
E_PARSE
E_USER_ERROR
-
catch
句で捕捉できるもの
→Error
Exception
(Exception
にはE_NOTICE
E_WARNING
E_USER_NOTICE
E_RECOVERABLE_ERROR
変換後のErrorException
が含まれる)
LogicException
/ RuntimeException
PHPプログラマ向けに提供されている Exception
の継承クラスとして, LogicException
と RuntimeException
があります.いろいろな記事で何回も言われていることですが,以下のような使い分けを行うべきです.
-
LogicException
… 自身のコード,あるいはそれを利用している第三者のコードにバグがあることを示す例外. -
RuntimeException
… 正しく取り扱っていても起こりうる例外.
以下では,これらを継承しているクラスの使い分けについて言及します.
BadFunctionCallException
/ BadMethodCallException
これは説明するほどでもないですね.
クラス名 | 継承元 | 利用シーン |
---|---|---|
BadFunctionCallException |
LogicException |
関数が未実装である場合, あるいは内部状態的に実行してはいけないタイミングで実行された場合の例外. |
BadMethodCallException |
LogicException |
メソッドが未実装である場合, あるいは内部状態的に実行してはいけないタイミングで実行された場合の例外. |
class Klass
{
public function __sleep()
{
throw new \BadMethodCallException('serialization is not supported');
}
}
serialize(new Klass); // BadMethodCallException
OverflowException
/ UnderflowException
マニュアルによれば,コンテナの「オーバーフロー」「アンダーフロー」にそのまま対応するようです.数値計算のオーバーフローがこれに当てはまるかは…どうだろう?
クラス名 | 継承元 | 利用シーン |
---|---|---|
OverflowException |
RuntimeException |
コンテナのオーバーフロー時の例外. |
UnderflowException |
RuntimeException |
コンテナのアンダーフロー時の例外. |
class Stack
{
private $elements = [];
private $size;
public function __construct(int $size)
{
if ($size < 1) {
throw new \LengthException("\$size must be positive integer, $size given");
}
$this->size = $size;
}
public function push($value)
{
if (count($elements) >= $size) {
throw new \OverflowException('container is full');
}
$this->elements[] = $value;
}
public function pop()
{
if (empty($this->elements)) {
throw new \UnderflowException('container is empty');
}
return array_pop($this->elements);
}
}
DomainException
/ InvalidArgumentException
/ LengthException
/ OutOfRangeException
/ OutOfBoundsException
/ RangeException
/ UnexpectedValueException
さぁ,見るからにここが一番混沌としています.正直なところ,今から書く説明があっているかどうかすら怪しいです…
LogicException
と RuntimeException
の分類ではなく,例外の内容で分類することにします.
引数や返り値のバリデーションを手広く行うもの
クラス名 | 継承元 | 利用シーン |
---|---|---|
DomainException |
LogicException |
型は合っているが,想定している いくつかの取りうる値のどれにも該当しなかった場合の例外. 自分を含め, InvalidArgumentException と一緒くたにされている気がするけど,もうちょっと使ってあげよう. |
RangeException |
RuntimeException |
型は合っているが,想定している いくつかの取りうる値のどれにも該当しなかった場合の例外. DomainException の実行時版. |
InvalidArgumentException |
LogicException |
引数の型が間違っている場合の例外. スカラータイプヒントおよび TypeError がPHP 7 から導入されたので,今後出番は減っていきそう… |
UnexpectedValueException |
RuntimeException |
返り値の型が想定外であった場合の例外. 引数はコンパイル時エラーでだいたい検出可能, 返り値は実行時でなければ検出できない …というスタンスで InvalidArgumentException と対になるのだろうか? |
コンテナへのアクセスのバリデーションを行うもの
クラス名 | 継承元 | 利用シーン |
---|---|---|
OutOfRangeException |
LogicException |
固定長であるコンテナのオフセットを無視したアクセスがあった場合の例外. 専ら SplFixedArray ,あるいはそれを踏襲した実装のために存在するようなもの. |
OutOfBoundsException |
RuntimeException |
可変長であるコンテナのオフセット, またはインデックスを無視したアクセスがあった場合の例外. マニュアルによると DomainException の実行時版であるらしいが,個人的には OutOfRangeException の実行時版のように思える. |
分類しづらいもの
クラス名 | 継承元 | 利用シーン |
---|---|---|
LengthException |
LogicException |
専ら「長さ」「大きさ」を表す自然数を バリデーションしたいときに使いそう. |
おまけ: バージョン別・エラーや例外の具体例
PHP 5.0 ~ 5.1 の検証は省略し,手元にある 5.5.34 および 7.0.9 で検証することにします.
<?php
function test($version, $code, $strict = false)
{
$trapped_code = ($strict ? 'declare(strict_types=1);' : '') . '
function preg_grep_keys($pattern, $input, $flags = 0) {
return array_intersect_key(
$input,
array_flip(preg_grep($pattern, array_keys($input), $flags))
);
}
set_error_handler(function ($errno, $errstr) use (&$cancel) {
$cancel = true;
$consts = array_flip(preg_grep_keys("/\AE_/", get_defined_constants()));
echo json_encode([
"type" => "`{$consts[$errno]}`",
"message" => $errstr,
]);
exit;
});
register_shutdown_function(function () use (&$cancel) {
if ($cancel || !$e = error_get_last()) return;
$consts = array_flip(preg_grep_keys("/\AE_/", get_defined_constants()));
echo json_encode([
"type" => "`{$consts[$e["type"]]}`",
"message" => $e["message"],
]);
});
try {
' . $code . '
} catch (\Exception $e) {
$cancel = true;
echo json_encode([
"type" => "[`" . get_class($e) ."`]",
"message" => $e->getMessage(),
]);
} catch (\Throwable $e) {
$cancel = true;
echo json_encode([
"type" => "[`" . get_class($e) ."`]",
"message" => $e->getMessage(),
]);
}
';
$error = json_decode(shell_exec(implode(' ', [
$version < 7 ? '/usr/bin/php' : '/usr/local/bin/php',
'-d error_reporting=-1',
'-d display_errors=0',
'-d log_errors=0',
'-r ' . escapeshellarg($trapped_code),
])));
return $error;
}
function escape_ascii($str)
{
return preg_replace_callback('/[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/', function ($m) {
return '&#' . ord($m[0]) . ';';
}, $str);
}
function build(array $items)
{
$tables = [
'|No.|概要|PHP 5.5.34|PHP 7.0.9| PHP 7.0.9 (strict)|',
'|:--|:--|:--|:--|:--|',
];
$codes = [];
$i = 0;
foreach ($items as $name => $code) {
$code = trim($code);
$err5 = test(5, $code);
$err7 = test(7, $code);
$err7s = test(7, $code, true);
$tables[] = sprintf('|%s|%s|%s|%s|%s|',
++$i,
$name,
$err5->type ?? '',
$err7->type ?? '',
$err7s->type ?? ''
);
$codes[] = implode("\n", [
'```php:' . escape_ascii("No.$i $name"),
$code,
'/*',
'PHP 5.5.34 : ' . ($err5->message ?? ''),
'PHP 7.0.9 : ' . ($err7->message ?? ''),
'PHP 7.0.9 (strict): ' . ($err7s->message ?? ''),
'*/',
'```'
]);
}
return implode("\n", $tables) . "\n\n" . implode("\n\n", $codes) . "\n";
}
echo build([
'未定義の変数の評価'
=> '
$undefined . "";
',
'未定義のグローバル定数の評価'
=> '
UNDEFINED . "";
',
'未定義の配列オフセットの評価'
=> '
$ary = [];
$ary[0] . "";
',
'未定義の連想配列インデックスの評価'
=> '
$asc = [];
$asc["undefined"] . "";
',
'未定義のインスタンスプロパティの評価'
=> '
$obj = new stdClass;
$obj->undefined . "";
',
'未定義の静的プロパティの評価'
=> '
$obj = new stdClass;
$obj::$undefined . "";
',
'未定義のクラス定数の評価'
=> '
$obj = new stdClass;
$obj::UNDEFINED . "";
',
'クラス経由でのインスタンスプロパティへのアクセス'
=> '
class Klass
{
public $prop;
}
Klass::$prop;
',
'アクセス権限のないプロパティへのアクセス'
=> '
class Klass
{
private static $prop;
}
Klass::$prop;
',
'ゼロ除算'
=> '
1 / 0;
',
'ゼロ剰余算'
=> '
1 % 0;
',
'マイナスのビットシフト'
=> '
1 << -1;
',
'配列と文字列の結合' => '
$ary = [];
$ary . ""; // PHP 7 のコンパイル時エラー回避
',
'配列変数と整数の加算' => '
$ary = [];
$ary + 1; // PHP 7 のコンパイル時エラー回避
',
'配列リテラルと整数の加算' => '
eval("[] + 1;"); // PHP 7 のコンパイル時エラー回避
',
'配列のオフセットの型間違い' =>'
$ary = [];
$ary[[]] . "";
',
'__toString()未実装時の文字列キャスト' =>'
$obj = new stdClass;
(string)$obj;
',
'__toString()の中でスローされる例外' =>'
class Klass
{
public function __toString()
{
throw new \Exception;
}
}
$obj = new Klass;
(string)$obj;
',
'__clone()の直接実行' =>'
class Klass
{
public function __clone()
{
return new self;
}
}
$obj = new Klass;
eval("\$obj->__clone();");// PHP 5 のコンパイル時エラー回避
',
'ArrayAccess未実装時の配列形式アクセス' =>'
$obj = new stdClass;
$obj[0] = 1;
',
'ユーザ定義関数のタイプヒンティングの無視' => '
function func(stdClass $obj) { }
func(1);
',
'ユーザ定義関数の引数不足' => '
function func($a) { }
func();
',
'組み込み関数のタイプ指定無視' => '
strlen([]);
',
'組み込み関数の引数不足' => '
strlen();
',
'組み込み関数の引数余剰' => '
strlen("", "");
',
'アサーションの失敗 (assert.exception=0)' => '
assert(false);
',
'アサーションの失敗 (assert.exception=1)' => '
ini_set("assert.exception", "1");
assert(false);
',
'foreachの型間違い' => '
$num = 1;
foreach ($num as $k => $v);
',
]);
No. | 概要 | PHP 5.5.34 | PHP 7.0.9 | PHP 7.0.9 (strict) |
---|---|---|---|---|
1 | 未定義の変数の評価 | E_NOTICE |
E_NOTICE |
E_NOTICE |
2 | 未定義のグローバル定数の評価 | E_NOTICE |
E_NOTICE |
E_NOTICE |
3 | 未定義の配列オフセットの評価 | E_NOTICE |
E_NOTICE |
E_NOTICE |
4 | 未定義の連想配列インデックスの評価 | E_NOTICE |
E_NOTICE |
E_NOTICE |
5 | 未定義のインスタンスプロパティの評価 | E_NOTICE |
E_NOTICE |
E_NOTICE |
6 | 未定義の静的プロパティの評価 | E_ERROR |
Error |
Error |
7 | 未定義のクラス定数の評価 | E_ERROR |
Error |
Error |
8 | クラス経由でのインスタンスプロパティへのアクセス | E_ERROR |
Error |
Error |
9 | アクセス権限のないプロパティへのアクセス | E_ERROR |
Error |
Error |
10 | ゼロ除算 | E_WARNING |
E_WARNING |
E_WARNING |
11 | ゼロ剰余算 | E_WARNING |
DivisionByZeroError |
DivisionByZeroError |
12 | マイナスのビットシフト | ArithmeticError |
ArithmeticError |
|
13 | 配列と文字列の結合 | E_NOTICE |
E_NOTICE |
E_NOTICE |
14 | 配列変数と整数の加算 | E_ERROR |
Error |
Error |
15 | 配列リテラルと整数の加算 | E_ERROR |
E_ERROR |
E_ERROR |
16 | 配列のオフセットの型間違い | E_WARNING |
E_WARNING |
E_WARNING |
17 | __toString()未実装時の文字列キャスト | E_RECOVERABLE_ERROR |
E_RECOVERABLE_ERROR |
E_RECOVERABLE_ERROR |
18 | __toString()の中でスローされる例外 | E_ERROR |
E_ERROR |
E_ERROR |
19 | __clone()の直接実行 | E_COMPILE_ERROR |
||
20 | ArrayAccess未実装時の配列形式アクセス | E_ERROR |
Error |
Error |
21 | ユーザ定義関数のタイプヒンティングの無視 | E_RECOVERABLE_ERROR |
TypeError |
TypeError |
22 | ユーザ定義関数の引数不足 | E_WARNING |
E_WARNING |
E_WARNING |
23 | 組み込み関数のタイプ指定無視 | E_WARNING |
E_WARNING |
TypeError |
24 | 組み込み関数の引数不足 | E_WARNING |
E_WARNING |
TypeError |
25 | 組み込み関数の引数余剰 | E_WARNING |
E_WARNING |
TypeError |
26 | アサーションの失敗 (assert.exception=0) | E_WARNING |
E_WARNING |
E_WARNING |
27 | アサーションの失敗 (assert.exception=1) | E_WARNING |
AssertionError |
AssertionError |
28 | foreachの型間違い | E_WARNING |
E_WARNING |
E_WARNING |
$undefined . "";
/*
PHP 5.5.34 : Undefined variable: undefined
PHP 7.0.9 : Undefined variable: undefined
PHP 7.0.9 (strict): Undefined variable: undefined
*/
UNDEFINED . "";
/*
PHP 5.5.34 : Use of undefined constant UNDEFINED - assumed 'UNDEFINED'
PHP 7.0.9 : Use of undefined constant UNDEFINED - assumed 'UNDEFINED'
PHP 7.0.9 (strict): Use of undefined constant UNDEFINED - assumed 'UNDEFINED'
*/
$ary = [];
$ary[0] . "";
/*
PHP 5.5.34 : Undefined offset: 0
PHP 7.0.9 : Undefined offset: 0
PHP 7.0.9 (strict): Undefined offset: 0
*/
$asc = [];
$asc["undefined"] . "";
/*
PHP 5.5.34 : Undefined index: undefined
PHP 7.0.9 : Undefined index: undefined
PHP 7.0.9 (strict): Undefined index: undefined
*/
$obj = new stdClass;
$obj->undefined . "";
/*
PHP 5.5.34 : Undefined property: stdClass::$undefined
PHP 7.0.9 : Undefined property: stdClass::$undefined
PHP 7.0.9 (strict): Undefined property: stdClass::$undefined
*/
$obj = new stdClass;
$obj::$undefined . "";
/*
PHP 5.5.34 : Access to undeclared static property: stdClass::$undefined
PHP 7.0.9 : Access to undeclared static property: stdClass::$undefined
PHP 7.0.9 (strict): Access to undeclared static property: stdClass::$undefined
*/
$obj = new stdClass;
$obj::UNDEFINED . "";
/*
PHP 5.5.34 : Undefined class constant 'UNDEFINED'
PHP 7.0.9 : Undefined class constant 'UNDEFINED'
PHP 7.0.9 (strict): Undefined class constant 'UNDEFINED'
*/
class Klass
{
public $prop;
}
Klass::$prop;
/*
PHP 5.5.34 : Access to undeclared static property: Klass::$prop
PHP 7.0.9 : Access to undeclared static property: Klass::$prop
PHP 7.0.9 (strict): Access to undeclared static property: Klass::$prop
*/
class Klass
{
private static $prop;
}
Klass::$prop;
/*
PHP 5.5.34 : Cannot access private property Klass::$prop
PHP 7.0.9 : Cannot access private property Klass::$prop
PHP 7.0.9 (strict): Cannot access private property Klass::$prop
*/
1 / 0;
/*
PHP 5.5.34 : Division by zero
PHP 7.0.9 : Division by zero
PHP 7.0.9 (strict): Division by zero
*/
1 % 0;
/*
PHP 5.5.34 : Division by zero
PHP 7.0.9 : Modulo by zero
PHP 7.0.9 (strict): Modulo by zero
*/
1 << -1;
/*
PHP 5.5.34 :
PHP 7.0.9 : Bit shift by negative number
PHP 7.0.9 (strict): Bit shift by negative number
*/
$ary = [];
$ary . ""; // PHP 7 のコンパイル時エラー回避
/*
PHP 5.5.34 : Array to string conversion
PHP 7.0.9 : Array to string conversion
PHP 7.0.9 (strict): Array to string conversion
*/
$ary = [];
$ary + 1; // PHP 7 のコンパイル時エラー回避
/*
PHP 5.5.34 : Unsupported operand types
PHP 7.0.9 : Unsupported operand types
PHP 7.0.9 (strict): Unsupported operand types
*/
eval("[] + 1;"); // PHP 7 のコンパイル時エラー回避
/*
PHP 5.5.34 : Unsupported operand types
PHP 7.0.9 : Unsupported operand types
PHP 7.0.9 (strict): Unsupported operand types
*/
$ary = [];
$ary[[]] . "";
/*
PHP 5.5.34 : Illegal offset type
PHP 7.0.9 : Illegal offset type
PHP 7.0.9 (strict): Illegal offset type
*/
$obj = new stdClass;
(string)$obj;
/*
PHP 5.5.34 : Object of class stdClass could not be converted to string
PHP 7.0.9 : Object of class stdClass could not be converted to string
PHP 7.0.9 (strict): Object of class stdClass could not be converted to string
*/
class Klass
{
public function __toString()
{
throw new \Exception;
}
}
$obj = new Klass;
(string)$obj;
/*
PHP 5.5.34 : Method Klass::__toString() must not throw an exception
PHP 7.0.9 : Method Klass::__toString() must not throw an exception, caught Exception:
PHP 7.0.9 (strict): Method Klass::__toString() must not throw an exception, caught Exception:
*/
class Klass
{
public function __clone()
{
return new self;
}
}
$obj = new Klass;
eval("\$obj->__clone();");// PHP 5 のコンパイル時エラー回避
/*
PHP 5.5.34 : Cannot call __clone() method on objects - use 'clone $obj' instead
PHP 7.0.9 :
PHP 7.0.9 (strict):
*/
$obj = new stdClass;
$obj[0] = 1;
/*
PHP 5.5.34 : Cannot use object of type stdClass as array
PHP 7.0.9 : Cannot use object of type stdClass as array
PHP 7.0.9 (strict): Cannot use object of type stdClass as array
*/
function func(stdClass $obj) { }
func(1);
/*
PHP 5.5.34 : Argument 1 passed to func() must be an instance of stdClass, integer given, called in Command line code on line 27 and defined
PHP 7.0.9 : Argument 1 passed to func() must be an instance of stdClass, integer given, called in Command line code on line 27
PHP 7.0.9 (strict): Argument 1 passed to func() must be an instance of stdClass, integer given, called in Command line code on line 27
*/
function func($a) { }
func();
/*
PHP 5.5.34 : Missing argument 1 for func(), called in Command line code on line 27 and defined
PHP 7.0.9 : Missing argument 1 for func(), called in Command line code on line 27 and defined
PHP 7.0.9 (strict): Missing argument 1 for func(), called in Command line code on line 27 and defined
*/
strlen([]);
/*
PHP 5.5.34 : strlen() expects parameter 1 to be string, array given
PHP 7.0.9 : strlen() expects parameter 1 to be string, array given
PHP 7.0.9 (strict): strlen() expects parameter 1 to be string, array given
*/
strlen();
/*
PHP 5.5.34 : strlen() expects exactly 1 parameter, 0 given
PHP 7.0.9 : strlen() expects exactly 1 parameter, 0 given
PHP 7.0.9 (strict): strlen() expects exactly 1 parameter, 0 given
*/
strlen("", "");
/*
PHP 5.5.34 : strlen() expects exactly 1 parameter, 2 given
PHP 7.0.9 : strlen() expects exactly 1 parameter, 2 given
PHP 7.0.9 (strict): strlen() expects exactly 1 parameter, 2 given
*/
assert(false);
/*
PHP 5.5.34 : assert(): Assertion failed
PHP 7.0.9 : assert(): assert(false) failed
PHP 7.0.9 (strict): assert(): assert(false) failed
*/
ini_set("assert.exception", "1");
assert(false);
/*
PHP 5.5.34 : assert(): Assertion failed
PHP 7.0.9 : assert(false)
PHP 7.0.9 (strict): assert(false)
*/
$num = 1;
foreach ($num as $k => $v);
/*
PHP 5.5.34 : Invalid argument supplied for foreach()
PHP 7.0.9 : Invalid argument supplied for foreach()
PHP 7.0.9 (strict): Invalid argument supplied for foreach()
*/