PHP Exception Handling - ErrorException

PHP Exception Handling – BadMethodCallException

Moving along through our detailed PHP Exception Handling series, today we’ll take a closer look at the BadMethodCallException in PHP, along with its lesser-used parent BadFunctionCallException. The primary scenario in which a BadMethodCallException is thrown is when calling either an instance or static method that doesn’t exist, or expects a different argument signature than the one provided.

In this article we’ll dig into the BadMethodCallException a bit more, looking at where it resides in the PHP Exception Hierarchy. We’ll also take a look at how BadMethodCallExceptions should be used and handled in your own coding endeavors, so let’s get movin’!

The Technical Rundown

Full Code Sample

Below is the full code sample we’ll be using in this article. Feel free to use any or all of the code if you wish to follow along.

When Should You Use It?

We have three examples that aim to illustrate how BadMethodCallExceptions and BadFunctionCallExceptions might come up. We start with the Book class, which contains a few property getters and setters, along with two PHP “magic methods”: __call() and __callstatic().

The __call() magic method triggers when an invalid instance method is called on a Book class instance. Similarly, the __callstatic() magic method is triggered when attempting to call an invalid static method. In both cases, the common technique is to throw a new BadMethodCallException indicating the problem. This ensures that a typo or incorrect method call is noticed immediately and can be remedied.

To see this in action, we start with the callInvalidInstanceMethod() function:

All we’re doing here is creating a new Book instance and then trying to call the checkout() method, which doesn’t exist. This throws a BadMethodCallException, as expected, which we catch and output:

Not too surprisingly, we’ll be using the callInvalidStaticMethod() method to test the Book::__callstatic() magic method:

We need very little logical code to properly test this one — all we need to do is to try calling the missing static Book::checkout() method. The output shows that our slightly different BadMethodCallException was thrown, as intended:

Now we run into a bit of a strange situation. As we saw in the hierarchy section above, BadMethodCallException inherits from the BadFunctionCallException class. However, causing a BadFunctionCallException is quite uncommon and is generally not considered appropriate in userland code. There are a few reasons for this, but the biggest reason is that PHP itself throws a fatal error when an attempt is made to call an invalid function. To illustrate, take a look at the callInvalidFunction() function:

Here we attempt to call the invalidFunction() function, which doesn’t exist in this context. One might expect a BadFunctionCallException to be thrown, but PHP doesn’t handle undefined functions that way. Instead, notice we’re also catching any Errors at the end of our catch block series. Sure enough, thanks to the ability to catch such errors in PHP 7+, the output shows that PHP threw an unexpected error because of our invalid function call:

While you could explicitly throw BadFunctionCallExceptions in your own code when a function isn’t properly invoked, with most modern object-oriented design patterns, the BadMethodCallException will likely be more appropriate to your needs.

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.