54166

[code]

    public function delete($id,$password){
    
        $stmt = $this->dbh->prepare("SELECT password FROM post_3 WHERE id = :id");
        $stmt->bindValue(':id',$id,PDO::PARAM_INT);
        $stmt->execute();
        $db_password = $stmt->fetchColumn();
        var_dump($db_password);
    
        if(!password_verify($password,$db_password)){
            throw new Exception('パスワードが違います');
        }
    
        $stmt = $this->dbh->prepare("DELETE FROM post_3 WHERE id = :id");
        $stmt->bindValue(':id',$id,PDO::PARAM_INT);
        $stmt->execute();
    
    }
    
[/code]

上記コードは簡易な掲示板のフォームより送信されたデータを元にデータベースの値を削除するメソッドなのですが、上記コードでは、try,catch文にて、データベース接続処理を書いていません。try,catch文内ではないのですが、「throw
new Exception('パスワードが違います');」  
と例外を投げることはできるのでしょうか？

実際に、エラーを出す為、

[code]

    if(!password_verify($password,$db_password)){
        throw new Exception('パスワードが違います');
    }
    
[/code]

ここの部分でfalseとなるように、間違ったパスワードを掲示板のフォームより入力し、動かしてみましたら、以下のように表示されました。

[code]

    Fatal error: Uncaught Exception: パスワードが違います in C:\xampp\xampp\htdocs\object_bbs.php\bbs_class1.php:100 Stack trace: #0 C:\xampp\xampp\htdocs\object_bbs.php\delete1.php(25): Bbs->delete(15, '1111111111') #1 {main} thrown in C:\xampp\xampp\htdocs\object_bbs.php\bbs_class1.php on line 100
    
[/code]

一応、「パスワードが違います」と例外を投げた際に記載した文字列が表示されています。  
これは、例外処理がなされた、ということなのでしょうか？

自分としましては、try,catch文内の、catchが出来なければ、例外を投げても受け取れないのではないのかなと思ったもので、疑問に思い質問させて貰いました。  
ご回答、頂けましたら幸いです。よろしくお願いいたします。


CC BY-SA 4.0
2019-04-14T12:39:42.753
54159
2019-04-15T05:30:20.603
2019-04-15T00:54:49.263
3060
32912
question
php
例外が投げられる条件


自分で `catch` を書かない場合、処理系ランタイムライブラリ中にある `catch` が例外を捕捉して実行エラーの表示となります。提示
[php](/questions/tagged/php "'php' のタグが付いた質問を表示") コードを `apache httpd`
で実行したなら、閲覧者には `500 Internal Server Error` になる（のかな？）

Q1. 自分で `catch` を書かずに `throw` してよいか？  
A1. 良いです。

Q2. このとき `catch` されるのか？  
A2. 処理系ランタイムライブラリが `catch` します。その結果は実行エラーになりますが、それがあなたの期待した動作かどうかは別問題。

Q3. 実行エラーにならないよう大域の `try` / `catch` を書くべきか  
A3. いいえ。そんなことするとデバッグできなくなります。最小限の例外種類を最小限の範囲で `try` / `catch`
し、自分で処理できない例外は上位にスルーしてください。

* * *

えっと [php](/questions/tagged/php "'php' のタグが付いた質問を表示") だから勝手に web application
であると思っていましたが httpd 関係なく php コンソールアプリケーションでしょうか？ まあどっちでも大差はないのすが

`try` / `catch` と `throw` は「責任の分担」に使います。そして `catch`
すべきは「自分が対処できるもののみ」であると覚えてください。

提示 `delete` は自分の責任として  
\- パスワードが違っていたら例外を投げる  
ところまでを担当しています。

パスワード違い例外発生時に具体的にどうすべきかは `delete` を呼ぶ側の責任である（ように現在設計されています）。そのため `catch` は
`delete` を呼ぶ側に書きます。

ユーザーがパスワードを誤って入力することは普通にありうる操作なので、上記仕様のまま行くなら `delete` を呼ぶ側に `try` / `catch`
を置いて、生成される `HTML` 上に「パスワードが違います」と出力するなど対処が必要です（対処しないと 500) 。

* * *

例外をどう使うかはプログラミング言語によって、プログラムの仕様を策定する人によって、違いがありますのでこの場で解説すると本が１冊書けちゃいます。

業務例外 と システム例外 で検索してみてください。

業務例外は発生すべくして発生するので `catch` して対処すべき  
\- ユーザーがパスワードを誤って入力することは普通にあり得る  
\- ユーザが複数タブ開いて削除操作をしたら、多重に記事削除しようとすることは普通にあり得る

システム例外とは端的にはプログラムのバグのことです。バグっていることが閲覧者に通知されても閲覧者は何もできないので、開発者がきっちりデバッグする必要があります。こういうのはデバッグの助けになるようエラーログを残したい。ランタイムライブラリの提供しているデフォルト例外ハンドラはエラーログを出力するので
`catch` しないことだけで事足ります。  
\- 配列の添え字があふれた  
\- SQL 文に文法エラーがある  
\- データベースに接続できない  
\- データーベース操作がタイムアウトした

繰り返しますが、必要な個所に必要な種類の `catch`
を最小限に書くようにしてください。そうするだけでデバッグがとても楽になります。開発中の未完成なプログラムがログ付きでエラー終了するのはとても正しいことですから（実用に供するまでには十分デバッグしてくださいね）


CC BY-SA 4.0
2019-04-15T02:52:11.413
54166
2019-04-15T05:30:20.603
2019-04-15T05:30:20.603
8589
8589
54159
answer