質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

PHPの例外処理について

解決済

回答 5

投稿

  • 評価
  • クリップ 4
  • VIEW 5,396

score 72

例外処理のcatch()の()の部分はどのような意味なのでしょうか?

例えば、

try{
  $obj = new SplFileObject($file, "rb");
}catch(Exception $e){
  echo $e->getMessage();
  exit();
}


catch(Exception $e)の部分の「Exception」は定義済みのクラスのことですよね?

$eはExceptionクラスのインスタンス(オブジェクト)という意味でしょうか?

$e->getMessage() はインスタンスである$eのgetMessagemeメソッドを使用しているということですよね?

$e = new Exception();


catchの()はこのような意味なのでしょうか?

初歩的なことですみませんが、ご回答いただきたいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+4

catchブロックは、tryブロック内でException(例外)が発生した場合に、Exception の種類ごとに、それを受け取って処理を行います。

例えば

try{

    //throw new ErrorException("error");                            // 1
    //throw new InvalidArgumentException("invalid argument");       // 2
    //throw new Exception("general");                               // 3
    //throw new PDOException("pdo");                                // 4

} catch(ErrorException $e){
    echo $e->getMessage();
    exit();
} catch(InvalidArgumentException $e){
    echo $e->getMessage();
    exit();
} catch(Exception $e){
    echo $e->getMessage();
    exit();
}

のようなコードがあるとして、

1をコメントアウトして活かし、ErrorExceptionをthrowすると1番目のcatchブロックでそれがキャッチされ、$eとして先程 new したErrorException(例外)のインスタンスが引数として渡されます。
ですから、

echo $e->getMessage();

の部分で、errorという文字が表示されます。

2を活かすとInvalidArgumentExceptionがthrowされるので2番目のcatchブロックでキャッチされて、invalid argument が表示されます。

3も同様で3番目のcatchブロックでキャッチされ general が表示されます。

4をコメントアウトすると new された PDOException のインスタンスが throw されますが、これ用の catch ブロックが存在しません。

ですが、PDOException は RuntimeException クラスを継承し、さらに RuntimeException クラスは Exception クラスを継承しているため、結果的に 3番目の catch ブロックでキャッチされ、やはり、pdo が表示されます。

このように、catch ブロックは try ブロック内で throw された Exception 毎にキャッチを行い、その際に new されたインスタンスを引数として取ります。

ですから、不正な実行結果の際に Exception(例外)を throw する関数等を try ブロック内に書いた場合、エラー処理が非常に簡単に行えるようになるわけです。

尚、全ての例外の基底クラス Exception クラスでは
http://php.net/manual/ja/class.exception.php

/* プロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;

となっていて、そのコンストラクタは
http://php.net/manual/ja/exception.construct.php

なため、

$e = new SomeException("hogehage");

のように new すると、第一引数の文字列が、そのインスタンスに対する

$e->getMessage();

という getMessage() メンバメソッドで取得できるというわけです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/03 18:28

    なお、
    parent::__construct($message, $code, $previous);
    は静的な関数コールですので、親クラスである Exception のインスタンスに対して関数呼び出しをしているわけではなく、インスタンスを生成せず、Exception クラスにあるコードをそのまま実行しているだけです。

    で、その実行結果は ValidationErrorException クラスのインスタンスのメンバ変数として保存されています。

    キャンセル

  • 2017/09/03 20:24

    親クラスのコンストラクタに任せられるものは任せるということですね。

    親切に教えていただきありがとうございました!

    キャンセル

  • 2017/09/05 00:42

    的確な回答と思います。評価させて頂きます。

    キャンセル

+4

catch(Exception $e)の部分の「Exception」は定義済みのクラスのことですよね?
$eはExceptionクラスのインスタンス(オブジェクト)という意味でしょうか?

PHP内部の定義済みのクラスのことで、定義済みの例外は他にもあります。PHP7ではError $eというのもあります。

もともと、PHPには「trycatch 例外処理」はありませんでした。

導入された際に例外の$eだけ特殊な扱いで型宣言しなくてはならない仕様で導入されました。
これがException $eです。

普通、オブジェクト指向言語では変数の型宣言をしなくてはなりません。ストリング(オブジェクト)型の変数$strの場合は、String $strという具合です。PHPは型を自動判断しましょうというコンセプトなので通常は型を書かず、例外の時だけException $eと書かなければいけません。

PHPマニュアルの型宣言について(タイプヒンティング)に型宣言できる型一覧が記載されてます。
例えばArray $arrayなどというように型を定義して変数宣言できます。こうすることで、配列以外の型を代入することはできなくなり、より厳密にプログラムを作成することができるようになります。

// 型宣言(タイプヒンティング)
function something (array $param = array()) {
    ...
};

something(array(1,2,3));  // OK
something(1)              // NG

$e->getMessage() はインスタンスである$eのgetMessagemeメソッドを使用しているということですよね?$e = new Exception();

正確にはtry{throw new \Exception();}catch(\Exception $e){}ですが、感覚的にはあってます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/03 19:39

    すみません、食べてたピーナッツが飛び出してしまいました(笑)

    キャンセル

  • 2017/09/03 19:41

    笑い事じゃないのは Tomak さんも良くわかってらっしゃるはずです、ええ。

    キャンセル

  • 2017/09/03 20:27

    通常クラスをインスタンス化するときは、インスタンスを作成して変数に代入する処理を一行でやっているが、
    例外処理ではインスタンスを作成する処理とインスタンスを変数に代入する処理を2つにわけているようなイメージですね。

    ありがとうございました!

    キャンセル

+1

基本はマニュアル

$eはtryでスローされたインスタンスですね

try{
  throw new Exception('ゼロによる除算。');
}catch(Exception $e){
 var_dump($e);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

マニュアルを見ていただければ、大体はわかると思います。

try {
    throw new Exception("エラーがあります。");
} catch(Exception $e) {
    echo $e->getMessage();
}


上記のように、例外に引っかかった時にcatch(Exception $e)"エラーがあります。"という引数が送られて、
$e->getMessage()で、その引数の文字列を呼び出していると考えればいいと思います。

間違っていたりしたら、申し訳ありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c

/* {{{ proto Exception|Error::__construct(string message, int code [, Throwable previous])
   Exception constructor */
ZEND_METHOD(exception, __construct)
{
    zend_string *message = NULL;
    zend_long   code = 0;
    zval  tmp, *object, *previous = NULL;
    zend_class_entry *base_ce;
    int    argc = ZEND_NUM_ARGS();

    object = getThis();
    base_ce = i_get_exception_base(object);

    if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, zend_ce_throwable) == FAILURE) {
        zend_class_entry *ce;

        if (Z_TYPE(EX(This)) == IS_OBJECT) {
            ce = Z_OBJCE(EX(This));
        } else if (Z_CE(EX(This))) {
            ce = Z_CE(EX(This));
        } else {
            ce = base_ce;
        }
        zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code [, Throwable $previous = NULL]]])", ZSTR_VAL(ce->name));
        return;
    }

    if (message) {
        ZVAL_STR(&tmp, message);
        zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp);
    }

    if (code) {
        ZVAL_LONG(&tmp, code);
        zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
    }

    if (previous) {
        zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_PREVIOUS), previous);
    }
}
/* }}} */

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る