Felipe Elia

ENPT

Improve your code with Early Return

5 min read
Early Return or guard clauses blog post by Felipe Elia.

For me, early return is the simplest and quickest technique to improve the readability of your code by 300%. It’s something I learned while collaborating with the WordPress core and I share it with everyone whenever I can.

The technique, also called guard clauses, consists of exiting the function as quickly as possible if some essential condition is not met. The most noticeable improvement is the removal of nested ifs. To make it easier to understand, let’s look at some code.

Imagine a WordPress function that makes changes to the search, but only if some conditions are met:

PHP
function felipeelia_change_search( $query ) {
	if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
		$current_site = get_current_blog_id();

		if ( 1 === $current_site ) {
			$search_term = $query->get( 's' );

			if ( strtolower( $search_term ) === 'super special search' ) {
				$post_type = $query->get( 'post_type' );

				if ( empty( $post_type ) ) {
				    // Only here we are actually doing something.
					$query->set( 'posts_per_page', '1' );

					$tax_query = [
						[
							'taxonomy' => 'category',
							'field'    => 'slug',
							'terms'    => 'news',
						],
					];
					$query->set( 'tax_query', $tax_query );

					$query->set( 'order', 'asc' );
				}
			}
		}
	}
}
add_action( 'pre_get_posts', 'felipeelia_change_search' );

Now the version with early returns or guard clauses :

PHP
function felipeelia_change_search_early_return( $query ) {
	if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
		return;
	}

	$current_site = get_current_blog_id();
	if ( 1 !== $current_site ) {
		return;
	}

	$search_term = $query->get( 's' );
	if ( strtolower( $search_term ) !== 'super special search' ) {
		return;
	}

	$post_type = $query->get( 'post_type' );
	if ( ! empty( $post_type ) ) {
		return;
	}

	$query->set( 'posts_per_page', '1' );

	$tax_query = [
		[
			'taxonomy' => 'category',
			'field'    => 'slug',
			'terms'    => 'news',
		],
	];
	$query->set( 'tax_query', $tax_query );

	$query->set( 'order', 'asc' );
}
add_action( 'pre_get_posts', 'felipeelia_change_search_early_return' );

Note that although the second version is a bit longer, the sequence of ifs and returns helps scan the code. Furthermore, the changes applied by our function are only indented once, instead of five!

Real-life example: early return in ElasticPress

Now another example, this time from the ElasticPress plugin. See how the Facets::is_facetable() method would look like without early returns :

PHP
public function is_facetable( $query ) {
	if ( ! \apply_filters( 'ep_is_facetable', false, $query ) ) {
		if ( ! is_admin() && ! is_feed() ) {
			if ( ! defined( 'WP_CLI' ) && ! WP_CLI ) {
				if ( $query->is_main_query() ) {
					$ep_integrate = $query->get( 'ep_integrate', null );

					if ( false !== $ep_integrate ) {
						$woocommerce = Features::factory()->get_registered_feature( 'woocommerce' );

						if ( $woocommerce->is_active() && function_exists( 'is_product_category' ) && is_product_category() ) {
							if ( $this->is_facetable_page( $query ) ) {
								return true;
							}						
						}
					}
				}
			}
		}	
	}
	return false;
}

Now the real version of the method:

PHP
public function is_facetable( $query ) {
	if ( \apply_filters( 'ep_is_facetable', false, $query ) ) {
		return true;
	}

	if ( is_admin() || is_feed() ) {
		return false;
	}

	if ( defined( 'WP_CLI' ) && WP_CLI ) {
		return false;
	}

	if ( ! $query->is_main_query() ) {
		return false;
	}

	$ep_integrate = $query->get( 'ep_integrate', null );
	if ( false === $ep_integrate ) {
		return false;
	}

	$woocommerce = Features::factory()->get_registered_feature( 'woocommerce' );
	if ( ! $woocommerce->is_active() && ( function_exists( 'is_product_category' ) && is_product_category() ) ) {
		return false;
	}

	if ( ! $this->is_facetable_page( $query ) ) {
		return false;
	}

	return true;
}

Much better, isn’t it?

Director’s Pro-Tip

Add your callout message here. Use this for tips, warnings, or key takeaways.

Performance First

Describe the first key point for your readers.

Secure by Default

Describe the second key point for your readers.

There is no silver bullet

Early returns or guard clauses are great, but they’re not the solution to everything. If your code has a lot of else statements, for example, consider breaking the function into smaller ones or you’ll end up with returns scattered throughout your code, making it harder to understand.

If you liked the post, don’t forget to share it!

Enjoyed this post? Get the next one by email.

New articles and useful tools, whenever there’s something worth sharing.

No fixed schedule. No spam. Unsubscribe anytime.