处理类的多次函数调用异常

3

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

请想象一下我的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吗?
什么是正确的做法?
帮帮我!
3个回答

3
通常在抛出异常的函数中,比如你的InsertQuestions方法中,你不想捕获任何异常,你想要抛出它们或让发生的异常“冒泡”。然后你的“控制器”代码可以确定如何处理异常。如果你的目标是在CreateQuizRecord失败时停止,我会将CreateQuizRecordInsertQuestions分别包装在它们自己的try块中。异常的一个优点是它们可以告诉你更多的信息,而不仅仅是一个简单的布尔值通过/失败。要么将基本异常扩展到诸如“Invalid_Parameter”之类的东西并测试特定异常,要么(不太理想地)从异常属性推断。你可以嵌套catch块以单独处理异常。
“从我的功能的catch中抛出QuizMakerException吗?” 是的,通常您在// Code to insert quiz下的代码本身将返回异常。比如说,如果模型无法插入,可能会引发数据库异常。在这种情况下,你可以让那个数据库异常冒泡,或者像你现在做的一样简单地捕获它,然后再抛出另一个异常(以某种方式使你的异常变得愚笨)。我这样看待它,每次调用都会抛出异常,并且后续的调用依赖于这个调用不抛出任何异常,应该被包装在一个try块中。假设你想要优雅地处理它,如果你只是想让它出错并停止,那就不要处理异常。你会得到一个错误和堆栈跟踪。有时候这是可取的。

我建议您在Github上查看一些代码。很容易搜索PHP项目并查看它们如何使用异常。Zend Framework可能提供一些很好的例子。 - ficuscr

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()
            );
        }
    }
}

在实际操作中,如果您无法正确插入记录,则会抛出插入异常。如果该代码块出现任何问题,您会捕获它并再次抛出插入异常。创建函数(或任何其他可能存在的函数)也是如此。

在主代码块中,您可以有:

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)并在其中检查抛出的每个异常类型以指定从那里采取的操作。希望对您有所帮助。

0
最好的做法是不要在第一时间抛出异常。 当程序崩溃时,会抛出异常,而它们并不用于处理错误输出。 如果您的函数返回任何值(即使是错误的),它就不需要异常。
回答您的问题,如果必须使用许多if/else,则必须使用它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接