PHP Exception Handling - ErrorException

PHP Exception Handling – TypeError

Next up in our in-depth PHP Exception Handling series we’re taking a closer look at the PHP TypeError. TypeErrors are thrown in a few different scenarios where the PHP engine expects a particular object type, but a different type is provided instead.

In this article we’ll explore the TypeError in more detail, looking at where it sits within the PHP Exception Hierarchy, and then examining some functional code samples that illustrate the three different scenarios in which TypeErrors can be thrown. Let’s get going!

The Technical Rundown

  • All PHP errors implement the Throwable interface, or are extended from another inherited class therein.
  • Error implements the Throwable interface.
  • TypeError extends the Error class.

When Should You Use It?

As previously mentioned, TypeError can be thrown in three different situations:

  • When a method declares an explicit argument type, but a different (incompatible) argument type is passed instead.
  • When a method declares an explicit return type, but a different typed is returned instead.
  • When an invalid number of arguments are passed to a built-in PHP function, while the declare() function of the executed file sets the strict_type declaration to true.

We’ll explore all three of these scenarios in our sample code, so we’ll start with the full working example below, then explore it in more detail to follow:

We begin with some simple classes, Book and Publisher, which both include a number of relevant properties like Publisher->name and Book->title. Most importantly, the getter and setter methods for these properties explicitly declare argument and return types, which is important for our use later on (and is generally a smart practice, anyway):

Our first function is testing what happens when we pass an invalid argument type to the Book->setPublisher(Publisher $publisher) method. Instead of passing an actual Publisher class instance object as the argument we’re passing a plain string to attempt to fix the publisher name to the proper one:

Since Book->setPublisher(Publisher $publisher) doesn’t expect a string argument, a TypeError is thrown in the output:

The obvious solution is to create a new Publisher instance and then pass it to the Book->setPublisher(Publisher $publisher) method:

The next scenario we might experience a TypeError is when a method’s return type is explicitly declared, but the method attempts to return a different type. In this second incorrectReturnTypeExample() function we’ve created a different book instance, and then make an explicit call to the $book->getPublisher() method. The return value of that call is passed to Logging::Log(string $value), which attempts to output a string value it receives:

Unfortunately, the Book->getPublisher() method has a minor issue — rather than returning the local Publisher object ($this->publisher), it instead returns a string value by returning the publisher’s name:

As a result of this incompatibility, executing the incorrectReturnTypeExample() function results in another TypeError, indicating the issue:

The solution here is to fix the Book->getPublisher() return type to its intended type, which is just $this->publisher:

The last scenario we could potentially experience a TypeError can only occur if our script has a declare() function statement that sets the strict_types declaration value to 1 (true). This is necessary because, by default, PHP attempts to convert certain value types into other, compatible types wherever applicable. For example, passing an integer value of 123 to a testMethod(string $value) method, which expects a string value as an argument, causes the integer to be automatically converted to a string ("123"). However, in some situations it may be useful to disallow this behavior in PHP, so attempting to automatically convert differing value types may result in an error.

As with any declare() statements, this must occur at the beginning of the file:

The incorrectArgumentCountExample() method declares an array with a few values, then passes it (along with two other arguments) to the built-in implode method, which only expects a maximum of two total arguments:

Since strict_types is enabled, passing an extra number of arguments to implode() results in a thrown TypeError:

Check out the Airbrake-PHP library, designed to quickly and easily integrate into any PHP project, giving you and your team access to real-time error monitoring and reporting throughout your application’s entire life cycle. With automatic, instantaneous error and exception notifications at your fingertips, you’ll be constantly aware of your application’s health, including any issues that may arise. Best of all, with Airbrake’s robust web dashboard cataloging every error that occurs, you and your team can immediately dive into the exact details of what went wrong, making it easy to quickly recognize and resolve problems.