Skip to content

Instantly share code, notes, and snippets.

Last active November 15, 2018 19:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaredcobb/a467c63b95ea5e79ffe0c0baf183ef8f to your computer and use it in GitHub Desktop.
Save jaredcobb/a467c63b95ea5e79ffe0c0baf183ef8f to your computer and use it in GitHub Desktop.
WordPress Best Practices

WordPress Best Practices



The WP_Query class is the recommended method of retrieving posts from WordPress. This class has several helper methods that take advantage of caching, performance, and long term stability.

Build Smarter Queries

By default, WP_Query performs about five database queries when fetching posts (i.e. calculating pagination and priming the term and meta caches.)

You can supress some of those additional queries if you don't need some of that additional data.

'no_found_rows' => true // useful when pagination is not needed.
'update_post_meta_cache' => false // useful when post meta will not be utilized.
'update_post_term_cache' => false // useful when taxonomy terms will not be utilized.
'fields' => 'ids' // useful when only the post IDs are needed.
Batching Queries

Never set posts_per_page => -1 (which would fetch unlimited posts). If your site contains thousands of posts, a single query can lock your database which may crash your site. Instead, get your posts in "batches".

function get_custom_posts() {
	// Determine if we have already cached our results.
	$cached_posts = get_transient( 'my_namespace_custom_posts' );

    // If we don't have any cached posts, execute the queries.
    if ( ! is_array( $cached_posts ) || empty( $cached_posts ) ) {
        // Set a batch number and initialize a posts array.
        $limit     = 100;
        $posts = [];

        // Customize your arguments as needed.
        $args = [
            'posts_per_page' => $limit,
            'post_status'    => 'publish',
            'post_type'      => 'my_custom_post_type',
            'paged'          => 1,
            'orderby'        => 'title',
            'order'          => 'ASC',
            'fields'         => 'ids',

        // Loop batches of queries until we have collected all our posts.
        do {
            $wp_query = new WP_Query( $args );
            // Ensure the query didn't fail and that we have some results.
            if ( ! is_wp_error( $wp_query ) && ! empty( $wp_query->posts ) ) {
                // Continue to merge each query's results.
                $posts = array_merge( $posts, $wp_query->posts );
            // Iterate to the next X batch of posts.
            $args['paged'] ++;
        } while ( $wp_query->post_count === $limit );
        // Cache the posts so that subsequent requests are faster.
        set_transient( 'my_namespace_custom_posts', $posts );
        return $posts;
Avoid get_posts()

Avoid using get_posts() unless you have good reason (which is uncommon). Using WP_Query allows WordPress to take advantage of several internal optimizations (such as automatic caching).

Avoid Meta Queries

Be careful with post meta queries (they can be very slow). If possible, when performing large queries, use taxonomy queries and structure your post data accordingly.

Direct Database Calls

Direct database queries should be avoided wherever possible. Instead, it’s best to rely on WordPress API functions for fetching and manipulating data.

Of course this is not always possible, so if any direct queries need to be run here are some best practices to follow:


By default, WordPress will cache your WP_Query results for about 5 mins. However there may situations where the data changes infrequently and it's better to cache your results infedinitely or until your data actually changes.


WordPress provides several helper functions that allow you to save, retrieve, and delete cached data.

Transients API

If persistent caching is configured on your server, then the transients functions will use the WP_Object_Cache. However if persistent caching has not been enabled, then the data will instead be cached to the options table.

Full Page Caching

Ultimately, WordPress builds the final HTML that needs to be delivered to your visitor. There are several caching plugins that save the final HTML to a file (on disk) and configure the server to look there first (bypassing the database all together).


Sanitize Input

Assume the worst! Most of the time, when users input data, the goal is to store it in the database. WordPress provides several helper functions that handle sanitizing the input which prevents security issues like cross site scripting (XSS) and SQL injection.

Escape Output

It's common to output text and content using echo however it's important to ensure we output only safe and allowed HTML tags.

More information on Validation, Sanitization, and Escaping:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment