1

現在、データベース処理に MySQLi プリペアード ステートメントを使用しています。MySQLi の準備済みステートメントは、接続が間違っている場合にのみエラーをスローするため、自分でエラーをチェックし、自分でエラーをスローする必要があります。PDO (私はこれを将来的に使用する予定です。これは、今でははるかにうまく機能すると確信しているためです) では、PDO が予想どおりにエラーをスローし、PDOException でキャッチできるため、はるかに優れたエラー処理が可能です。

しかし今のところ、私は MySQLi に行き詰まっているので、現在のコードが適切な方法であるかどうかを知りたいですか? 多くのチュートリアルや本で同様のワークフローを見つけることができますが、いくつかの場所で「例外を使用して、一部のメソッドが失敗したことをユーザーに通知することは非効率的であり、悪い習慣と見なされます」と読みました。( http://www.sitepoint.com/forums/showthread.php?872057-should-i-use-1-or-many-try-catches-in-a-page-that-uses-PDO )

try{
    $user = $dataUser->getById(1);
}catch(UserNotFoundException $unfe){
    echo 'No user found with the provided id';
}catch(Exception $exc){
    //do some logging with the real exception
    ...
    //show a readable error to the website visitor
    echo "There was an error retrieving the user from the database.";
}

In my function I use something like this:
function getById($id){
    $query = "select user_id, username,firstname from users where user_id = ?";
    if ($stmt = $this->database->getConnection()->prepare($query)) {
        $stmt->bind_param('i',$id);
        if($stmt->execute()){
                throw new exception('There was an error retrieving the user by id: ' . $stmt->error);
        }
        $stmt->bind_result($userId,$username);      
        $stmt->store_result();
        $stmt->fetch();                                             
        if(($stmt->num_rows) == 1){
            $stmt->close();         
        $user = new User($username);
        $user->userId = $userId;
        $user->username = $username;
        return $user;               
        }else{
            $stmt->close();
        throw new UserNotFoundException("No user found matching the id.");
        }
    }else{          
        throw new Exception("There was a database error retrieving the user by id: " .    $this->database->getConnection()->error);
    }
}

「あなたの常識」のコメントに基づくUPDATE 1

mysqli_report(MYSQLI_REPORT_ALL);それほどうまく機能していません..

私はいくつかの練習をしましたが、例外とエラーの正確な違いはまだ明確ではありません。PDO を使用すると、実行が失敗したときに例外がスローされます。Mysqli はそうではありません。自分で確認してから投げる必要があります。データベースラッパーを使用して呼び出すとしましょう:

  $this->db->getOne($query,'id');

このメソッドのどこかに $stmt->execute が現れます。成功したかどうかを確認して例外をスローする必要がありますか、それともここでエラーをトリガーする必要がありますか?

error_handler を提案しているためです。

pdo を使用する場合、exception_handler を使用する必要があるため、混乱しますか?

更新 2

  1. アヤックスはどうですか?JSON を使用して結果を返します。エラーが発生した場合、ここで try catch を使用して json.success true または false を返す必要がありますか? または、ここでエラーをどのように処理すればよいですか?

  2. より具体的な情報を表示したい場合はどうすればよいですか? たとえば、ユーザーが登録を実行し、すでに登録されているユーザー名や電子メールを使用すると、一意のキーに違反しているため、エラーがスローされます。しかし、「500 エラーが発生しました」と表示したいだけではありません。この場合、「このユーザー名が使用されています」など、登録者が問題を把握していることが重要だからです。

    このような場合、詳細な情報を表示したいので、try catch が適切な方法であるというのは正しいでしょうか?

try catch を使用するタイミングと、グローバル エラー ハンドラーにエラーを処理させるタイミングについて混乱しています。このトピックで私はこれを読みました

「 set_exception_handler() を使用して、カスタム関数でキャッチされていない例外を処理できます。ただし、「正しい」方法は、試してみることです...たとえばクエリを実行するときに例外をキャッチし、カスタム関数を使用してログに記録しますそれに応じて。」しかし、それはこのトピックでは悪い習慣と見なされます。

4

2 に答える 2

1

私の現在のコードは良い習慣ですか?

いいえ、多くの点で。

まず、この例外的なことで、mysqli はようやく対処しました。

mysqli_report(MYSQLI_REPORT_ALL);

mysqli に例外をスローするように指示します。まだ、

例外を使用して、一部のメソッドが失敗したことをユーザーに通知することは非効率的であり、悪い習慣と見なされます

丁度。ついに、これらすべての役に立たないチュートリアルや本に対抗できるほど賢い人が現れました。

//do some logging with the real exception

アプリケーションのすべてのクエリはかなり...冗長です。そう思わない?まだ、

//show a readable error to the website visitor

それは「読める」ものではありません。はい、平易な英語です。しかし、サイト訪問者はデータベースと何の関係があるのでしょうか? どのユーザー?「拾う」とは?これらはすべて役に立たず、混乱を招きます。たとえば、このサイトなど、いくつかの専門的に構築されたサイトを見てください。一般的な 500 エラー ページのみを表示するため、技術的な詳細について負担をかけることはありません。

また、コードで行うすべての操作に対して行うのではなく、set_error_handler() を使用して集中的に行う必要があります。

例外は、エラー自体を処理するためにのみ使用する必要があります。

したがって、try..catch ブロックは完全に冗長です。エラーが発生した場合は、エラー ハンドラーによって例外をキャッチする必要があり、エラーがログに記録され、一般的な 500 エラー ページが表示されます。

throw new exception('There was an error retrieving the user by id: ' . $stmt->error);

クエリの実行ごとに追加されるこのコードは、非常に冗長だと思いませんか? 本当に必要なのは、すべての汚い仕事を行うためのデータベース ハンドラー クラスです。

この関数がどのように見えるか見てください:

function getById($id)
{
    $query = "select username from users where user_id = ?";
    $name  = $this->db->getOne($query,$id);
    return new User($name);
}

すべてのデータベース操作に対して 2 つの行。

(ただし、 User クラスを作成するというあなたの考えは非常に奇妙です)

于 2013-08-15T09:06:50.843 に答える
1

Serenarules 氏の次の言葉に同意します。役に立たない: エラー メッセージはエラー ログに記録されます。ユーザーはそのような詳細で何ができますか? ほとんどの場合、「エラー 500」で十分です。

データベース接続の KO は、例外が発生する現実の問題です。ただ、個人的には「IDに一致するユーザーが見つかりませんでした」というケースが考えられます。例外を発生させないでください。代わりに、このケースは単にアプリケーションの動作を変更する必要があります。エラーログでこれらのイベントをリッスンしたくない場合は?

于 2013-08-15T09:20:59.430 に答える