391
356

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

お前は PHP 7 における Fatal Error / Catchable Fatal Error / Error / ErrorException / Exception の違いを言えるか?

Last updated at Posted at 2016-08-04

導入

煽りタイトルすいません.PHP 7 のエラーや標準例外について,違いを整理し,使い分けを考察する記事です.

【引用】 PHP 7.0.0α2 の例外の例外の継承関係を可視化してみた by @ngyuki

7e7426e0-d147-1443-980b-3a9e5ae1e68f.png

すべてを捕捉対象にする [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点の違いや使い分けについて言及します.

旧来のエラー

【引用】 $_GET, $_POSTなどを受け取る際の処理

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_handlerErrorException を組み合わせると幸せになるかも

set_error_handler(function($severity, $message, $file, $line) {
    throw new ErrorException($message, 0, $severity, $file, $line);
});

但し,ここで設定したハンドラは Fatal Error を受け取ることができず,どうしてもそれに対処したい場合は [register_shutdown_function] を使って「最後の悪あがき」をする程度しか方法がありません.

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_ERRORE_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
No.1 未定義の変数の評価
$undefined . "";
/*
PHP 5.5.34        : Undefined variable: undefined
PHP 7.0.9         : Undefined variable: undefined
PHP 7.0.9 (strict): Undefined variable: undefined
*/
No.2 未定義のグローバル定数の評価
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'
*/
No.3 未定義の配列オフセットの評価
$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
*/
No.4 未定義の連想配列インデックスの評価
$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
*/
No.5 未定義のインスタンスプロパティの評価
$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
*/
No.6 未定義の静的プロパティの評価
$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
*/
No.7 未定義のクラス定数の評価
$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'
*/
No.8 クラス経由でのインスタンスプロパティへのアクセス
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
*/
No.9 アクセス権限のないプロパティへのアクセス
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
*/
No.10 ゼロ除算
1 / 0;
/*
PHP 5.5.34        : Division by zero
PHP 7.0.9         : Division by zero
PHP 7.0.9 (strict): Division by zero
*/
No.11 ゼロ剰余算
1 % 0;
/*
PHP 5.5.34        : Division by zero
PHP 7.0.9         : Modulo by zero
PHP 7.0.9 (strict): Modulo by zero
*/
No.12 マイナスのビットシフト
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
*/
No.13 配列と文字列の結合
$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
*/
No.14 配列変数と整数の加算
$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
*/
No.15 配列リテラルと整数の加算
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
*/
No.16 配列のオフセットの型間違い
$ary = [];
$ary[[]] . "";
/*
PHP 5.5.34        : Illegal offset type
PHP 7.0.9         : Illegal offset type
PHP 7.0.9 (strict): Illegal offset type
*/
No.17 __toString()未実装時の文字列キャスト
$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
*/
No.18 __toString()の中でスローされる例外
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: 
*/
No.19 __clone()の直接実行
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): 
*/
No.20 ArrayAccess未実装時の配列形式アクセス
$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
*/
No.21 ユーザ定義関数のタイプヒンティングの無視
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
*/
No.22 ユーザ定義関数の引数不足
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
*/
No.23 組み込み関数のタイプ指定無視
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
*/
No.24 組み込み関数の引数不足
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
*/
No.25 組み込み関数の引数余剰
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
*/
No.26 アサーションの失敗 (assert.exception=0)
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
*/
No.27 アサーションの失敗 (assert.exception=1)
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)
*/
No.28 foreachの型間違い
$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()
*/

[SplFixedArray]: http://www.php.net/manual/ja/class.splfixedarray.php
[register_shutdown_function]: http://php.net/manual/ja/function.register-shutdown-function.php
[set_error_handler]: http://php.net/manual/ja/function.set-error-handler.php
[trigger_error]: http://php.net/manual/ja/function.trigger-error.php
[Throwable]: http://www.php.net/manual/ja/class.throwable.php
[Exception]: http://www.php.net/manual/ja/class.exception.php
[ErrorException]: http://www.php.net/manual/ja/class.errorexception.php
[Error]: http://www.php.net/manual/ja/class.error.php
[ArithmeticError]: http://www.php.net/manual/ja/class.arithmeticerror.php
[AssertionError]: http://www.php.net/manual/ja/class.assertionerror.php
[DivisionByZeroError]: http://www.php.net/manual/ja/class.divisionbyzeroerror.php
[ParseError]: http://www.php.net/manual/ja/class.parseerror.php
[TypeError]: http://www.php.net/manual/ja/class.typeerror.php
[BadFunctionCallException]: http://www.php.net/manual/ja/class.badfunctioncallexception.php
[BadMethodCallException]: http://www.php.net/manual/ja/class.badmethodcallexception.php
[DomainException]: http://www.php.net/manual/ja/class.domainexception.php
[InvalidArgumentException]: http://www.php.net/manual/ja/class.invalidargumentexception.php
[LengthException]: http://www.php.net/manual/ja/class.lengthexception.php
[LogicException]: http://www.php.net/manual/ja/class.logicexception.php
[OutOfBoundsException]: http://www.php.net/manual/ja/class.outofboundsexception.php
[OutOfRangeException]: http://www.php.net/manual/ja/class.outofrangeexception.php
[OverflowException]: http://www.php.net/manual/ja/class.overflowexception.php
[RangeException]: http://www.php.net/manual/ja/class.rangeexception.php
[RuntimeException]: http://www.php.net/manual/ja/class.runtimeexception.php
[UnderflowException]: http://www.php.net/manual/ja/class.underflowexception.php
[UnexpectedValueException]: http://www.php.net/manual/ja/class.unexpectedvalueexception.php

391
356
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
391
356

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?