2
\$\begingroup\$

I'm using this piece of code to show and paginate only child categories but this is horribly slow (49 queries in 9,799 seconds.).

Where did I make mistakes and how can I make this run faster?

<?php
$current_cat = get_query_var('cat');
$attributes = array('terms_per_page' => 20, 'taxonomy' => 'category');
// Sanitize and validate our inputs and set variables
$tpp = filter_var( $attributes['terms_per_page'], FILTER_VALIDATE_INT );
$taxonomy = filter_var( $attributes['taxonomy'], FILTER_SANITIZE_STRING );
// Make sure our taxonomy exists to avoid unnecessary work
if ( !taxonomy_exists( $taxonomy ) )
return false;
// Our taxonomy exists, lets continue
// Get the term count to calculate pagination.
$term_count = count( get_terms('category',array('hide_empty'=>'1','child_of' => $current_cat) ) );
// We have terms, now calculate pagination
$max_num_pages = ceil( $term_count / $tpp );
// Get current page number. Take static front pages into account as well
if ( get_query_var('paged')){
$paged = get_query_var('paged');
} elseif ( get_query_var('page')) {
$paged = get_query_var( 'page' );
} else {
$paged = 1;
}
// Calculate term offset
$offset = ( ( $paged - 1 ) * $tpp );
// We can now get our terms and paginate it
$args = array(
'number' => $tpp, // Amount of terms to return
'offset' => $offset, // The amount to offset the list by for pagination
'child_of' => $current_cat,
'orderby' => 'name', 
'order' => 'ASC', 
'hide_empty' => '1',
);
// Set our variable to hold our string
$output = '';
$wpbtags = get_terms( $taxonomy, $args );
if ( ! empty($wpbtags)) {
foreach ($wpbtags as $category) { 
//first get the current category ID
$cat_prefix = "category_";
$cat_id = $category->term_id;
//then i get the data from the database
$join_cat = $cat_prefix . $cat_id;
$cat_data = get_option($join_cat);?>
<a href="<?php echo get_category_link($category->term_id); ?>" onclick="ga('send', 'event', 'ClickNav', 'cats', 'Cat - <?php echo $category- >cat_name; ?>');">
<div class="one_fourth<?php echo ( ++$counter == 4 )?' last_column':''; ?> home-colour" title="<?php echo $category->name; ?>">
<?php if (!empty($cat_data['cat_img_url'])) : ?>
<h2 style="text-align:center"> <?php echo $category->name; ?> </h2>
<img class="res_img" src="<?php echo $cat_data['cat_img_url'] ;?>" alt="<?php echo $category->cat_name; ?>" width="310" height="209" />
<?php elseif (empty($cat_data['cat_img_url'])) :?>
<h2 style="text-align:center"> <?php echo $category->name; ?> </h2>
<img class="res_img" src="<?php echo get_stylesheet_directory_uri(); ?>/images/subcat-img-na.png" alt="Posts - <?php echo $category->cat_name; ?>"/>
<?php else : ?>
<?php endif; ?>
</div><!-- eof cat div --> </a>
<?php } ?> 
<?php /* COUNTS FOUR ADDS LAST COLUMN */ if ( $counter == 4 ) : ?>
<div class='clear'> </div>
<?php $counter = 0; endif; wp_reset_query(); ?>
<div class='clear'> </div>
<?php echo '<div class="wp-pagenavi" style="text-align:center">';
$big = 999999999; // need an unlikely integer
echo paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $max_num_pages = (ceil( $term_count / $tpp))
) );
echo '</div>';
?> 
<?php wp_reset_postdata(); ?>
<?php /* IF THERE'S NOTHING TO SHOW */ } else {?>
// Show something if there is no posts here
<?php } ?>
asked Feb 18, 2017 at 20:02
\$\endgroup\$
3
  • \$\begingroup\$ Does horribly slow mean it needs days, hours or minutes? How slow is slow and how fast should it be? \$\endgroup\$ Commented Feb 19, 2017 at 14:12
  • \$\begingroup\$ @t3chb0t Sorry, I should provide a reference to "horribly slow" (49 queries in 9,799 seconds.). I already edited the question. Anything faster is a great improvement. Thanks! \$\endgroup\$ Commented Feb 19, 2017 at 14:24
  • \$\begingroup\$ That's great. Now it deserves some votes ;-) \$\endgroup\$ Commented Feb 19, 2017 at 14:26

1 Answer 1

1
\$\begingroup\$

The real problem here is that you are querying in loops (almost always a bad pattern) because you are relying on built-in Wordpress querying functions, rather than writing raw SQL to query all this data at once.

My guess is you can do a single query to get both the paginated results and the total number of rows without limit being applied (by using SQL_CALC_FOUND_ROWS).

You might consider opening StackOverflow question specifically about the multiple/slow query problems along with information on your database tables relevant to these queries to get a suggestion on how to write an appropriate query.


Outside of that, I find your code incredibly difficult to read, and while some of that might have to do with following style conventions in Wordpress (which really bad IMO), you should at least indent you code and place comments properly (i.e. not prepending comment on code lines).

answered Feb 20, 2017 at 17:49
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.