Transient not working for custom loops

I have actually worked on a post yesterday (check it out here) and was hit by the same problem. I’m also new to the Transient API, never actually worked with it :-).

The problem here is that for a specific loop you need to use a certain value outside of your transient. You are simply storing the wrong values, and because of this, you are getting these overload of db hits.

To explain, here is part of the code from the answer I’ve referred to. I need to create a list of categories with post titles belonging to these categories. To accomplish this, I run my custom query and then use the value of $q to create my list

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a="<a href="". get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

This gives me 6 queries in 0.06348 seconds.

OK, if you look at what the example from the codex, you should put your new WP_Query result in a transient. If I do that, the results is totally haywire

<?php
if( false === ( $query = get_transient('custom_query') ) ) {
    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 
 set_transient('custom_query', $query, 60 * MINUTE_IN_SECONDS);
}
    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a="<a href="". get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();


?>

With the code above, my results looks like this 31 queries in 0.19141 seconds. This is 25 queries more and takes about 0.13 seconds more. The reason for this is, for each post, WordPress needs to revisit the db to retrieve the categories the post belongs to, as this is not stored in you transient. 25 extra queries is the amount of posts in my db. So, you see, you have actually wasted a lot of resources by storing the wrong info. I do not need the info from the new WP_Query, but the result/value from $q

So, to properly make use of transients, you have to store the correct values you are after. To do this, I need to add my complete query into a transient to make sure that it is only run once, and that is when the transient is created. After that, the custom query is not needed anymore and is redundant, the only thing that needs to be stored and that I’m after now is the value $q. So, this is how the query is altered to remove the custom query after the transient is created, and to save just the value of $q

Just to note, I’ve changed my transient names along the way just for testing purposes to show the times and queries. Also note that when creating your transient, you need to use the value (in this case $q) you need to save

 if ( false === ( $q = get_transient( 'category_list' ) ) ) {

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a="<a href="". get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

set_transient( 'category_list', $q, 12 * HOUR_IN_SECONDS );
}

This give me 2 queries in 0.00195 seconds. You see how I have now effectively made use of transients. $q which is an array of many values` is now available to create my list, and it only cost me 2 db hits to accomplish my goal

I hope this all makes sense

Leave a Comment