morganestes
5/10/2017 - 7:41 PM

High-performance WP_Query for custom post types

High-performance WP_Query for custom post types

<?php
/** High-performance, cached query for custom post types */

namespace Morgan_Estes\WP_Query;

/**
 * Gets the cache group used by the plugin.
 *
 * @since x.x.x
 * @uses  \apply_filters()
 *
 * @return string The filtered cache group.
 */
function get_cache_group() {
	/**
	 * Filter the key used in caching.
	 *
	 * @since x.x.x
	 *
	 * @param string $cache_group Default ''.
	 */
	$cache_group = apply_filters( 'my_prefix_cache_group', '' );

	return (string) $cache_group;
}

/**
 * Gets a collection of posts with a custom query.
 *
 * @since x.x.x
 *
 * @param bool $force_cache Optional. Whether to force a cache flush.
 * @return array A collection of {@see \WP_Post} posts (or custom array of data).
 */
function custom_wp_query( $force_cache = false ) {
	$cache_key = 'my_custom_post_type_query';
	$results   = wp_cache_get( $cache_key, get_cache_group(), $force_cache );

	if ( $force_cache || false === $results ) {
		$results    = [];
		$query_args = [
			'post_type'              => [ 'my_custom_post_type' ],
			'post_status'            => [ 'publish' ],
			'orderby'                => 'menu_order',
			'no_found_rows'          => true,
			'update_post_meta_cache' => false,
			'update_post_term_cache' => false,
		];
		$query      = new \WP_Query( $query_args );

		if ( $query->have_posts() ) {
			while ( $query->have_posts() ) {
				// Optionally, pick parts of the post and create a custom collection.
				$query->the_post();
				$results[] = get_post();
			}

			wp_reset_postdata();

			wp_cache_set( $cache_key, $results, get_cache_group(), WEEK_IN_SECONDS );
		}
	}

	return $results;
}

/**
 * Triggers an object cache flush for our custom query.
 *
 * @since    x.x.x
 * @internal Callback for 'save_post_{post_type}' action.
 */
function flush_custom_wp_query_cache() {
	custom_wp_query( true );
}

// Flushes the object cache for the query when a post is updated.
add_action( 'save_post_my_custom_post_type', __NAMESPACE__ . '\\flush_custom_wp_query_cache' );