try...catch

try

(PHP 5, PHP 7, PHP 8)

try ブロックは、処理が必要な Throwable エラーを throw する可能性があるコードを囲むもので、 対応する catch ブロックあるいは finally ブロックが 必ずひとつ以上必要です。

try ブロック内で Throwable エラーがスローされると、 PHP はそのエラーを処理するため、最初にマッチする catch ブロックを探します。 見つからなければ、マッチするブロックが見つかるか、 グローバルなエラーハンドラに到達するまで、コールスタックを巻き戻します。

注意:

set_exception_handler() を使うと、 キャッチされないあらゆる Throwable を処理するハンドラを設定できます。 これは、コード全体を try-catch ブロックで囲むのと似ています。

catch

(PHP 5, PHP 7, PHP 8)

catch ブロックには、スローされた Throwable エラーにどのように対処するかを記述します。 このブロックには、処理できる Throwable のサブクラス (多くの場合は Exception 配下のクラス) をひとつ以上指定します。 オプションで、例外を代入する変数も指定できます。

スローされた Throwable オブジェクトのクラスにマッチする 最初の catch ブロックが、そのエラーを処理します。 通常の実行はその catch ブロックの後から再開され、 他にマッチする catch ブロックがあっても、それらは実行されません。

例1 例外をキャッチする

<?php
try {
    throw new Exception('Error');
} catch (Exception $e) {
    echo 'Caught exception: ', $e->getMessage(), "\n";
}

// 実行は継続される
echo "Hello World\n";

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

Caught exception: Error
Hello World

PHP 7.1.0 以降では、catch ブロックで処理する Throwable のサブクラスを、 パイプ文字 (|) を使った union で指定できるようになりました。 これは、異なるクラス階層に由来する異なる例外を同じように処理したい場合に有用です。

例2 処理するクラスを union で指定してキャッチする

<?php

class MyException extends Exception { }

class MyOtherException extends Exception { }

class Test {
    public function testing() {
        try {
            throw new MyException();
        } catch (MyException | MyOtherException $e) {
            var_dump(get_class($e));
        }
    }
}

$foo = new Test;
$foo->testing();

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

string(11) "MyException"

複数の catch ブロックを使うと、 異なるクラスの Throwable エラーをそれぞれ異なる方法で処理できます。 try ブロック内でエラーがスローされなかった場合は、 連続して定義された最後の catch ブロックの後から、通常どおり実行が続きます。

例3 複数の catch ブロック

<?php
try {
    do_something_io_related();
} catch (FileNotFoundException $e) {
    // FileNotFoundException だけをキャッチして、その場合の処理を行う
} catch (MissingPermissionException $e) {
    // MissingPermissionException だけをキャッチして、その場合は別の処理を行う
}

catch ブロックの中から Throwable を throw する (あるいはスローしなおす) こともできます。 何もスローされなければ、通常どおり実行が再開されます。

例4 ネストした例外

<?php

class MyException extends Exception { }

class Test {
    public function testing() {
        try {
            try {
                throw new MyException('foo!');
            } catch (MyException $e) {
                // スローしなおす
                throw $e;
            }
        } catch (Exception $e) {
            var_dump($e->getMessage());
        }
    }
}

$foo = new Test;
$foo->testing();

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

string(4) "foo!"
警告

catch ブロックの中でスローしたオブジェクトは、 隣接する catch ブロックではキャッチされません。

例5 連続した catch ブロック

<?php

class A extends Exception {}
class B extends Exception {}

try {
    throw new A;
} catch (A $e) {
    throw new B;
} catch (B) {
    echo 'Hello';
}

上の例の出力は、 たとえば以下のようになります。

Fatal error: Uncaught B in /in/K8Tl9:9
Stack trace:
#0 {main}
  thrown in /in/K8Tl9 on line 9

PHP 8.0.0 以降では、キャッチされた Throwable に対応する変数はオプションになりました。 指定されない場合、catch ブロックは実行されるものの、 スローされたオブジェクトへアクセスすることはできません。

例6 キャッチするときに変数を省略する

PHP 8.0.0 以降でのみ許されます。

<?php

class SpecificException extends Exception {}

function test() {
    throw new SpecificException('Oopsie');
}

try {
    test();
} catch (SpecificException) {
    print "A SpecificException was thrown, but we don't care about the details.";
}

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

A SpecificException was thrown, but we don't care about the details.
+add a note

User Contributed Notes

There are no user contributed notes for this page.