Errors-Try-Catch

Handling PHP errors paves the way for resilient code

For the past 72 articles, we’ve lived life on the optimistic side. Never once did we stop to think that errors might be occurring. We are programmers and we are great at what we do. Why would we think that we should ever worry about error handling? Oh, the users that use our application. Who cares? They should know how to enter valid data when prompted. When we say that they should enter their age, clearly we mean that this should be a number (integer) and not a string. If they don’t know how to follow directions, that’s on them. They might brake the database you say? Okay, that’s more of a concern.

As terrible as it is to say out loud, treat each user of your application like an absolute idiot. Don’t say that to their face, but think it behind the scenes. I wouldn’t blame you even if you chuckled as you allow yourself to scream “idiot” inside your head. You wouldn’t be too far from the truth. People will find ways to break your application, intentionally or unintentionally. It’s up to you to guard it with all your might.

https://blog.devgenius.io/php-p72-errors-intro-83e7b58700d5

Getting Serious about Errors

As of PHP 7, errors are reported by throwing the Error exception. What are type of errors that we can encounter?

  • ArithmeticError is the error that’s thrown during a failed mathematical operation.
  • DivisionByZeroError is a type of ArithmeticError that occurs when you try to divide by zero.
  • AssertionError is thrown when an assertion fails.
  • CompileError is thrown for compilation errors.
  • ParseError is a type of CompileError that occurs while parsing PHP code. You’ll see this error occur, for example, with the use of the eval() function.
  • TypeError occurs when the data type is not correct in a few scenarios, such as with class property mismatch, when argument types do not match declared parameter types, or when the return type is different from the declaration.
  • ArgumentCountError is a type of TypeError. It occurs when a method has a predefined set of parameters but too few arguments are passed to it.
  • ValueError is a tricky one. It occurs when the datatype is correct, but the expected value is incorrect. For example, expecting positive integers but receiving a negative one.
  • UnhandledMatchError occurs when there’s no arm for the match expression.
  • FiberError is thrown on invalid operations on a Fiber function.

Not catching an error

We can create an error quickly in PHP to test and see what happens. Create a new php file and write: echo 10/0;

You’ll get an error.

Fatal error: Uncaught DivisionByZeroError: Division by zero in /home/user/scripts/code.php:3
Stack trace:
#0 {main}
  thrown in /home/user/scripts/code.php on line 3

There’s our DivisionByZero error that we looked at earlier. The interesting part is that it says Uncaught. We didn’t catch it. But how do we catch an error? With the try/catch block.

Try/Catch

A try/catch block represents a way for you to test something out, and if it doesn’t work, catch the error before it’s displayed on the screen and provides the user with negative UX.

<?php

try 
{
  // Try some code here
} 
catch( SomeErrorCode $error ) 
{
  // If your code failed above, catch it if it matches the catch Error code
}

What could we try inside of our try block? We could try to execute our echo 10/0; statement. Place that into your try { } block body.

<?php

try
{
    echo 10 / 0;
}
catch( SomeErrorCode $error )
{
    // If your code failed above, catch it if it matches the catch Error code
}

We know that in this instance the error that will be thrown is the DivisionByZero error. We saw it we tried out the code earlier and PHP returned that there was an Uncaught error. A DivisionByZero is just a datatype. It’s a datatype that was created by PHP developers. Think of it as a string or an int datatype. If you read my previous articles, you’ll remember that you can declare the datatype of the parameter.

https://blog.devgenius.io/php-p48-type-declarations-47114a7a0e0b

Let’s catch our DivisionByZero error. We’ll catch it inside of our catch() statement.

<?php

try
{
    echo 10 / 0;
}
catch( DivisionByZeroError $error )
{
    // If your code failed above, catch it if it matches the catch Error code
}

Run the code. A blank screen should appear. We caught the error and prevented it from appearing on the screen! It’s now stored in our $error variable. We can handle it gracefully like sending out an email stating that there was an error that occurred or logging it to our Log file. We could also just echo out something more user friendly.

<?php

try
{
    echo 10 / 0;
}
catch( DivisionByZeroError $error )
{
    echo "Dear idiot user. You cannot divide by zero";
}

Run the code again and you’ll see that the message Dear idiot user. You cannot divide by zero is displayed on the screen.

To see what the $error object holds, just use var_dump and dump it to the screen.

/app/72 Errors/72 Errors Intro.php:10:
object(DivisionByZeroError)[1]
  protected 'message' => string 'Division by zero' (length=16)
  private 'string' (Error) => string '' (length=0)
  protected 'code' => int 0
  protected 'file' => string '/app/72 Errors/72 Errors Intro.php' (length=34)
  protected 'line' => int 5
  private array 'trace' (Error) => 
    array (size=0)
      empty
  private ?Throwable 'previous' (Error) => null
  public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> DivisionByZeroError: Division by zero in /app/72 Errors/72 Errors Intro.php on line <i>5</i></th></tr>
<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align=''... (length=842)

Why Test Such a Thing?

Why would we want to test such a thing? We know that 10 / 0 will always throw the DivisionByZeroError, so why even bother? User input. We may get input from the user and have something like this instead:

echo 10 / $_POST['user_number'];

The user can then type in whatever they want in the form, and when they click submit, the information is sent over to be processed. If they enter 0, the error will be caught.

Chaining Catch Statements

What if they enter something other than a number? What if the user enters a letter? We get a new type of error.

Fatal error: Uncaught TypeError: Unsupported operand types: int / string in /home/user/scripts/code.php:3Stack trace:
#0 {main}
  thrown in /home/user/scripts/code.php on line 3

The error that’s received is a TypeError. How do we catch it? We’ve already caught our DivisionByZeroError. Where do we place the catch for the TypeError. You’ll just chain onto it.

<?php

try
{
    echo 10 / "a";
}
catch( DivisionByZeroError $error )
{
    echo "Dear idiot user. You cannot divide by zero";
}
catch( TypeError $error )
{
    echo "Dear idiot user. You must use a number";
}

A More Generic Catch

Could there be other errors that arise? Of course. If we want to make sure that all of our errors are handled, at the end of the try/catch/catch/…/catch statement, we’ll need to add a more generic catch statement that catches anything that might have been missed. Just like you can catch a division by zero error with both the DivisionByZeroError and the ArithmeticError handlers (since DivisionByZeroError is of type ArithmeticError), you can catch any error with the Error handler. Everything that we looked at above, like TypeError, is of type Error.

<?php

try
{
    echo 10 / 0;
}
catch( DivisionByZeroError $error )
{
    echo "Dear idiot user. You cannot divide by zero";
}
catch( TypeError $error )
{
    echo "Dear idiot user. You must use a number";
}
catch( Error $error )
{
    echo "Dear idiot user. I have no idea how you got here but I caught it";
}

The Finally Statement

What if you wanted to execute a piece of code each time, regardless of whether an error is caught or not? You can do that with the finally statement.

If you run the code above, you’ll get:

Dear idiot user. You cannot divide by zero
Dear idiot user. This code always executes.

Conclusion

I think we went as deep into errors as I would like to go in this article. They’re pretty straight forward. I’ve seen developers struggle with the try/catch concept. Just think of it like an if/else statement where if = try and else = catch. If you have multiple conditions, you start introducing the if/elseif/else statement. Similar concept with try/catch/catch.

Errors Intro

PHP ERRORS SIGNAL CODE HICCUPS THAT NEED ATTENTION

PHP – P72: Errors intro

Bugs are normally errors in code that the programmer coded, that produce a result, and that result is not correct.

Errors-Try-Catch

Handling PHP errors paves the way for resilient code

PHP – P73: Errors

We are programmers and we are great at what we do. Why would we think that we should ever worry about error handling?

FORMS CAPTURE DATA, CONNECTING USERS AND SYSTEMS.

PHP – P74:FORMS INTRODUCTION

We’ve gone through enough syntax that we’re ready to start looking at some actual concrete examples, like form processing. We’re going to introduce databases and data-persistence in a later article. All we want to know is how do we send data from a form on the client end to a server, wherever that server may live.

Leave a Reply