Junaid Bhura a web developer in Melbourne, Australia - specializing in WordPress development.

Exceptions in WordPress: About time?


Update: I’ve created a ticket on WordPress trac: https://core.trac.wordpress.org/ticket/57842. If you like this idea, then please show your support there, so we can get something like this merged into WordPress core!


I think a good introduction to error handling in WordPress would be this article from Ryan McCue from way back in 2012.

TLDR: The WP_Error object was introduced into WordPress before PHP even had support for Exceptions!

The age of that blog post demonstrates a few things:

  1. Time flies!
  2. The WP_Error object is really old
  3. WordPress has been around for a really long time

The WP_Error object has since tied into a lot of core functionality and a lot of critical functionality like the REST API has been built on top of it.

So it looks like WP_Error isn’t going to go away anytime soon. And it doesn’t have to for us to start using PHP Exceptions in our custom code that are not intended for public consumption – that is – until WordPress core supports it out of the box.

In the meantime, I’ve come up with the following Exception class that is meant to:

  1. Be compatible with WP_Error
  2. Be able to convert from WP_Error
  3. Be able to convert to WP_Error
<?php
/**
 * WordPress does not provide a standard Exception Class.
 * Use this instead until something similar gets merged into core.
 */

namespace Junaidbhura;

use Exception;
use WP_Error;

/**
 * Exception Class.
 */
class WP_Exception extends Exception {

	/**
	 * Error code, similar to WP_Error.
	 *
	 * @var int|string Error code.
	 */
	protected int|string $error_code = ''; // phpcs:ignore

	/**
	 * Error data, similar to WP_Error.
	 *
	 * @var mixed Data.
	 */
	protected mixed $error_data = [];

	/**
	 * Constructor.
	 *
	 * @param int|string $error_code    Error code.
	 * @param string     $error_message Error message.
	 * @param mixed      $error_data    Error data.
	 */
	public function __construct( int|string $error_code = '', string $error_message = '', mixed $error_data = [] ) {
		$this->error_code = $error_code;
		$this->error_data = $error_data;

		parent::__construct( $error_message );
	}

	/**
	 * Get error code.
	 *
	 * @return int|string
	 */
	public function get_error_code(): int|string {
		return $this->error_code;
	}

	/**
	 * Get error message.
	 *
	 * @return string
	 */
	public function get_error_message(): string {
		return parent::getMessage();
	}

	/**
	 * Get error data.
	 *
	 * @return mixed
	 */
	public function get_error_data(): mixed {
		return $this->error_data;
	}

	/**
	 * Convert a WP_Error into this Exception.
	 *
	 * @param WP_Error $wp_error WP_Error object.
	 *
	 * @return $this
	 */
	public function from_wp_error( WP_Error $wp_error ): WP_Exception {
		$this->error_code = $wp_error->get_error_code();
		$this->message    = $wp_error->get_error_message();
		$this->error_data = $wp_error->get_error_data();

		return $this;
	}

	/**
	 * Convert this exception into a WP_Error.
	 *
	 * @return WP_Error
	 */
	public function to_wp_error(): WP_Error {
		return new WP_Error(
			$this->get_error_code(),
			$this->get_error_message(),
			$this->get_error_data()
		);
	}

}

Sample usage:

use Junaidbhura\WP_Exception;

// Normal Exception.
try {
	throw new WP_Exception( 'error_code', 'Error message', $error_data );
} catch ( WP_Exception $e ) {
	$e->get_error_code();
	$e->get_error_message();
	$e->get_error_data();
}

// To WP Error.
try {
	my_function();
} catch ( WP_Exception $e ) {
	return $e->to_wp_error(); // Returns a WP_Error based on the exception.
}

// From WP Error.
if ( is_wp_error( $thing ) ) {
	$exception = new WP_Exception();
	throw $exception->from_wp_error( $thing );
}

Leave a Reply

Your email address will not be published. Required fields are marked *