Search code examples
phpexceptioncustom-exceptions

Handling exceptions for multiple calls to functions of a class


I can't get my head around WHEN to throw and catch exceptions for when I call functions from classes.

Please imagine that my QuizMaker class looks like this:

// 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;
        }
    }
}

... and using this code, I use the class to create a new quiz in the database

    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
}

For this piece of code, I want to call a QuizMakerException if any of the functions don't perform what I want them to (at the moment they return TRUE or FALSE).

What is the correct way to go about catching when any of the functions in this code does not perform what I want them to? At the moment they simply return TRUE or FALSE.

  • Do I really have to put lots of if/else statements between calling each function, I thought that was the whole point in exceptions, they simply halt the execution of further statements within the try/catch?
  • Do I throw a QuizMakerException from within the catch of my functions?

What is the right thing to do?

Help!


Solution

  • Well typically in the function which throws the exception, say your InsertQuestions method, you don't want to catch any exceptions, you want to throw them or let ones occurring to "bubble up". Then your "controller" code can make the determination of how to handle the exception.

    If your goal here is to halt if CreateQuizRecord fails I would wrap CreateQuizRecord and InsertQuestions each in their own try block.

    One advantage of exceptions is they can tell you more than a simple bool pass/fail. Either extending your base exception into things like "Invalid_Parameter" and testing for specific exceptions or -less ideally- inferring from properties of the exception. You can nest your catch blocks to handle exceptions individually.

    Do I throw a QuizMakerException from within the catch of my functions?

    Yes. Typically your code under // Code to insert quiz would itself return an exception. Say if the Model failed to insert it might be raising a database exception. In which case you can let that database exception bubble up, or do what you sort of doing now and catch it simply to in turn throw another exception (kinda dumbs down your exceptions in a way, doing that though).

    Do I really have to put lots of if/else statements between calling each function, I thought that was the whole point in exceptions, they simply halt the execution of further statements within the try/catch?

    I look at it like this, each call which throws an exception and is followed by a subsequent call which depends on this one not throwing any exceptions, should be wrapped in a try block. Assuming you want to handle it gracefully, if you simply want it to error out and halt just don't handle the exception. You'll get an error and stack trace. Sometimes that is desirable.