【问题标题】:Handling exceptions for multiple calls to functions of a class处理对类函数的多次调用的异常
【发布时间】:2012-09-06 19:30:28
【问题描述】:

当我从类中调用函数时,我无法理解何时抛出和捕获异常。

请想象我的QuizMaker 类看起来像这样:

// Define exceptions for use in class
private class CreateQuizException extends Exception {}
private class InsertQuizException extends Exception {}

class QuizMaker()
{

    // Define the items in my quiz object
    $quiz_id = null;
    $quiz_name = null;

    // Function to create a quiz record in the database
    function CreateQuizInDatabase()
    {

        try
        {

            $create_quiz = // Code to insert quiz

            if (!$create_quiz)
            {
                // There was an error creating record in the database
                throw new CreateQuizException("Failed inserting record");
            }
            else
            {
                // Return true, the quiz was created successfully
                return true;
            }

        }
        catch (CreateQuizException $create_quiz_exception)
        {
            // There was an error creating the quiz in the database
            return false;
        }
    }

    function InsertQuestions()
    {
        try
        {
            $insert_quiz = // Code to insert quiz

            if (!$insert_quiz)
            {
                // There was an error creating record in the database
                throw new CreateQuizException("Failed inserting quiz in to database");
            }
            else
            {
                // Success inserting quiz, return true
                return true;
            }
        }
        catch (InsertQuizException $insert_exception)
        {
            // Error inserting question
            return false;
        }
    }
}

...并使用此代码,我使用该类在数据库中创建一个新测验

    class QuizMakerException extends Exception {}

try
{
    // Create a blank new quiz maker object
    $quiz_object = new QuizMaker();

    // Set the quiz non-question variables
    $quiz_object->quiz_name = $_POST['quiz_name'];
    $quiz_object->quiz_intro = $_POST['quiz_intro'];
            //... and so on ...

    // Create the quiz record in the database if it is not already set
    $quiz_object->CreateQuizRecord();

    // Insert the quiz in to the database
    $quiz_object->InsertQuestions();

}
catch (QuizMakerException $quiz_maker_error)
{
    // I want to handle any errors from these functions here
}

对于这段代码,如果任何函数没有执行我希望它们执行的操作(此时它们返回 TRUE 或 FALSE),我想调用 QuizMakerException

当这段代码中的任何函数没有执行我希望它们执行的操作时,正确的方法是什么?目前他们只是返回 TRUE 或 FALSE。

  • 我是否真的必须在调用每个函数之间放置大量 if/else 语句,我认为这就是异常的全部意义所在,它们只是停止执行 try/catch 中的进一步语句?
  • 我是否会从我的函数的 catch 中抛出 QuizMakerException?

什么是正确的做法?

救命!

【问题讨论】:

    标签: php exception exception-handling custom-exceptions


    【解决方案1】:

    通常在抛出异常的函数中,比如你的InsertQuestions 方法,你不想捕获任何异常,你想抛出它们或让它们发生“冒泡”。然后你的“控制器”代码可以决定如何处理异常。

    如果您的目标是在 CreateQuizRecord 失败时停止,我会将 CreateQuizRecordInsertQuestions 分别包装在各自的 try 块中。

    异常的一个优点是它们可以告诉您的不仅仅是简单的布尔通过/失败。将您的基本异常扩展到“Invalid_Parameter”之类的内容并测试特定异常,或者 - 不太理想 - 从异常的属性中推断。你可以嵌套你的 catch 块来单独处理异常。

    我是否会从我的函数捕获中抛出 QuizMakerException?

    是的。通常,// Code to insert quiz 下的代码本身会返回异常。假设模型未能插入它可能会引发数据库异常。在这种情况下,您可以让该数据库异常冒泡,或者做您现在正在做的事情并简单地捕获它,然后再抛出另一个异常(虽然这样做有点使您的异常变得愚蠢)。

    我真的必须在调用每个函数之间放置大量 if/else 语句吗,我认为这就是异常的全部意义所在,它们只是停止执行 try/catch 中的进一步语句?

    我是这样看的,每个抛出异常的调用,然后是依赖于这个不抛出任何异常的后续调用,都应该包装在一个 try 块中。假设您想优雅地处理它,如果您只是想让它出错并停止,请不要处理异常。你会得到一个错误和堆栈跟踪。有时这是可取的。

    【讨论】:

    • 我建议看看 github 上的一些代码。搜索 PHP 项目并查看它们如何使用异常非常容易。 Zend Framework 可能会提供一些很好的例子。
    【解决方案2】:

    您可能想稍微改变一下结构。你的 QuizMaker 类可以变成:

    <?php
    
    // Define exceptions for use in class
    public class CreateQuizException extends Exception {}
    public class InsertQuizException extends Exception {}
    
    class QuizMaker()
    {
    
        // Define the items in my quiz object
        $quiz_id = null;
        $quiz_name = null;
    
        // Function to create a quiz record in the database
        function CreateQuizInDatabase()
        {
    
            try
            {
    
                $create_quiz = // Code to insert quiz
    
                if (!$create_quiz)
                {
                    // There was an error creating record in the database
                    throw new CreateQuizException("Failed inserting record");
                }
                else
                {
                    // Return true, the quiz was created successfully
                    return true;
                }
    
            }
            catch (Exception $create_quiz_exception)
            {
                // There was an error creating the quiz in the database
                throw new CreateQuizException(
                    "Failed inserting record " . 
                    $create_quiz_exception->getMessage()
                );
            }
        }
    
        function InsertQuestions()
        {
            try
            {
                $insert_quiz = // Code to insert quiz
    
                if (!$insert_quiz)
                {
                    // There was an error creating record in the database
                    throw new InsertQuizException("Failed inserting quiz in to database");
                }
                else
                {
                    // Success inserting quiz, return true
                    return true;
                }
            }
            catch (Exception $insert_exception)
            {
                // Error inserting question
                throw new InsertQuizException(
                    "Failed inserting quiz in to database " . 
                    $create_quiz_exception->getMessage()
                );
            }
        }
    }
    

    实际上,如果您无法正确插入记录,则会引发 Insert 异常。如果该代码块出现任何问题,您将捕获它并再次抛出一个 Insert 异常。 Create 函数(或您可能拥有的任何其他函数)也是如此。

    在主代码块中你可以有:

    try
    {
        // Create a blank new quiz maker object
        $quiz_object = new QuizMaker();
    
        // Set the quiz non-question variables
        $quiz_object->quiz_name = $_POST['quiz_name'];
        $quiz_object->quiz_intro = $_POST['quiz_intro'];
                //... and so on ...
    
        // Create the quiz record in the database if it is not already set
        $quiz_object->CreateQuizRecord();
    
        // Insert the quiz in to the database
        $quiz_object->InsertQuestions();
    
    }
    catch (InsertQuizException $insert_exception)
    {
        // Insert error
    }
    catch (CreateQuizException $create_quiz_exception)
    {
        // Create error
    }
    catch (Exception $quiz_maker_error)
    {
        // Any other error
    }
    

    如果您不想在那里有多个 catch 块,只需保留 catch(Exception) 一个,然后在其中检查引发的每个异常的类型,以指定从那里采取的操作。

    HTH

    【讨论】:

      【解决方案3】:

      最好的办法是一开始就不必抛出异常。 当程序崩溃时抛出异常并且它们不是用来处理错误输出的。 如果你的函数返回任何东西(甚至是错误的东西),它不需要异常。

      要回答您的问题,如果需要使用大量 if/else,那么您必须使用它们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多