0

I'm a little stuck on how this hook is used. Does it go in the search template, the archive page, or in functions? Does it surround the pagination code? Also, does it work differently when I'm querying a taxonomy archive page?

I guess I may as well include all of my code here. Everything works fine except for pagination issues, which are different depending on whether you're on the archive page, or whether you've done a search on that page.

The biggest problem right now is the search results page. It shows the pagination links just fine. But when you click on any page number, it changes to the right number in the URL, but the results don't change.

The secondary problem is that on the actual archive page, clicking the numbered pagination links works great. I get the url http://www.domain.com/imagetags/library/page/57/ for instance. And then if I instead enter a page number in the jump box (let's say, 23), it takes me to the correct place, but with this URL - http://www.domain.com/imagetags/library/page/57/?page=23

Everything is good up to that point. BUT, if from that jumped-to link I then click on one of the numbered pagination links again, it will change the /page/25/ but because the /?page=23 remains, the images showing don't change at all. Surely there's a way to make the jump box do the same URL as the pagination links?

But again, the part I need the most urgently fixed is the search results page. I'm assuming though, that getting that fixed will likely fix my taxonomy page as well (hopefully).

Thanks in advance.

Here's my taxonomy page:

<?php
/**
* The TAXONOMY template file
*
* This is the category template file in a WordPress theme
*
* @link https://codex.wordpress.org/Template_Hierarchy
*
* @package WordPress
* @subpackage ansel
* @since 1.0
* @version 2.0
*/

get_header();

// Current Taxonomy
global $post;
$objCT = get_queried_object();

// Page to render
$paged = (get_query_var('page')) ? get_query_var('page') : 1;

// Args
$args = array(
   'post_type' => 'attachment',
   'post_mime_type' => 'image',
   'tax_query' => array(
      array(
         'taxonomy' => $objCT->taxonomy,
         'field' => 'term_id',
         'terms' => $objCT->term_id
      )
   ),
   'orderby' => 'title',
   'order' => 'asc',
   'posts_per_page' => '21',
   'paged' => $paged,
   'post_status' => 'inherit'
);

// The Loop
$wp_query = new WP_Query( $args ); ?>

<div id="post-<?php the_ID(); ?>" <?php post_class(''); ?>>
   <div class="content container-fluid" style="padding: 0 !important;">
      <div class="row justify-content-center">
         <div class="col-md-9">
            <h1 class="header__title">
               <i class="fas fa-map-marker-alt"></i> <?php echo $objCT->name; ?>
            </h1>
            <?php $current = $objCT;
            $current_term_id = $current->term_id;
            $current_name = $current->name;
            $current_taxonomy = $current->taxonomy;
            $current_parent = $current->parent;
            $sub_terms = get_terms( array(
               'taxonomy' => $current_taxonomy,
               'child_of' => $current_parent,
               'hide_empty' => true,
            ) );

            // only start if some sub terms exist
            if ($sub_terms) {
               if($current_term_id && $current_parent) {
                  // shows on parent taxonomy pages ?>
                  <div id="accordion">
                     <div class="card">
                        <div class="card-header" id="headingOne">
                           <h5 class="mb-0">
                              <button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
                                 <i class="fas fa-sort-amount-down"></i> Filter by Sub-categories <span class="justify-content-end arrow"><i class="fas fa-arrow-circle-down"></i></span>
                              </button>
                           </h5>
                        </div>

                        <div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
                           <div class="card-body">
                              <div class="terms row">
                                 <?php foreach ($sub_terms as $sub_term) { ?>
                                    <a class="sub-term col-xl-3 col-lg-4 col-md-4 col-sm-6 col-xs-6" href="<?php echo get_term_link($sub_term); ?>">
                                       <div class="box">
                                          <div class="onhover"><?php echo $sub_term->name; ?></div>
                                       </div>
                                    </a>
                                 <?php } ?>
                              </div>
                           </div>
                        </div>
                     </div>
                  </div>
               <?php }
            }

            // shows on sub-taxonomy pages
            $terms3 = get_terms(['taxonomy' => get_queried_object()->taxonomy, 'parent'=> get_queried_object_id(), 'hide_empty' => false]);
            if($terms3) { ?>
               <div id="accordion">
                  <div class="card">
                     <div class="card-header" id="headingTwo">
                        <h5 class="mb-0">
                           <button class="btn btn-link" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
                              <i class="fas fa-sort-amount-down"></i> Filter by Sub-categories <span class="justify-content-end arrow"><i class="fas fa-arrow-circle-down"></i></span>
                           </button>
                        </h5>
                     </div>

                     <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordion">
                        <div class="card-body">
                           <div class="terms row">
                              <?php foreach ( $terms3 as $term3) { ?>
                                 <a class="sub-term col-xl-3 col-lg-4 col-md-4 col-sm-6 col-xs-6" href="<?php echo get_term_link( $term3 ); ?>">
                                    <div class="box">
                                       <div class="onhover"><?php echo $term3->name; ?></div>
                                    </div>
                                 </a>
                              <?php } ?>
                           </div>
                        </div>
                     </div>
                  </div>
               </div>
            <?php } ?>

            <main>
               <div class="container-fluid">

               <?php ansel_pagination(); ?>

               <div class="row justify-content-center">
                  <div class="container-fluid">
                     <div class="grid">
                        <div class="grid-sizer"></div>
                           <?php $c = 0;
                           while (have_posts()): the_post();
                              $item = get_the_id();
                              $atts = wp_get_attachment_image_src($item, 'medium_large');
                              $url = strtok($atts[0], '?');
                              $atts_full = wp_get_attachment_image_src($item, 'full');
                              $image_all = wp_prepare_attachment_for_js($item);
                              $attachment_page = wp_get_attachment_url( $item );
                              $title = wp_prepare_attachment_for_js($item);
                              $image_title = wp_prepare_attachment_for_js($item);
                              $img = $atts_full[0];

                              ini_set('user_agent','Mozilla/4.0 (compatible; MSIE 6.0)');
                              $file = file_get_contents($img);
                              $animated=preg_match('#(\x00\x21\xF9\x04.{4}\x00\x2C.*){2,}#s', $file);
                           ?>
                           <style>
                              .grid-item img#image<?php echo $c; ?> {
                                 display: block;
                                 width: 100%;
                              }

                              .img-overlay-wrap.<?php echo int_to_words($c); ?> .overlay<?php echo $c; ?> {
                                 position: absolute;
                                 top: 0;
                                 left: 0;
                                 opacity: 0;
                                 -webkit-transition: opacity .25s ease-in; 
                                 transition: opacity .25s ease-in;
                              }

                              .img-overlay-wrap.<?php echo int_to_words($c); ?>:hover .overlay<?php echo $c; ?> {
                                 opacity: 100%;
                              }
                           </style>

                           <div class="grid-item">
                              <?php if(has_term('poster', 'mediacat', $item) && !has_term('standees', 'mediacat', $item)) {
                                 $frame = get_field('poster_frame', 'option');
                              ?>
                              <script>
                                 jQuery(function($){
                                    $(".overlay<?php echo $c; ?>").css("width", $('#image<?php echo $c; ?>').get(0).getBoundingClientRect().width + "px");

                                    $(".overlay<?php echo $c; ?>").css("height", $('#image<?php echo $c; ?>').get(0).getBoundingClientRect().height + "px");
                                 });
                              </script>

                              <div class="img-overlay-wrap <?php echo int_to_words($c); ?>">
                              <?php } ?>

                              <div class="watermark"><img id="image<?php echo $c; ?>" src="<?php if ($animated==1){ echo $atts_full[0]; } else { echo $url; } ?>" alt="<?php echo $image_all['alt']; ?>"></div>

                                 <?php if(has_term('poster', 'mediacat', $item) && !has_term('standees', 'mediacat', $item)) { ?>
                                    <img class="overlay<?php echo $c; ?> overlay" src="<?php echo $frame; ?>">
                              </div>
                           <?php } ?>


                        <div class="entry-content-box">
                           <p class="entry-text"><strong>Photo ID:</strong> <?php echo $image_title['title']; ?></p>
                           <?php if($image_all['caption'] || $image_all['alt']) { ?>
                              <p class="entry-text"><strong>Keywords</strong></p>
                              <div class="keywords">
                                 <?php $unique_id = esc_attr( uniqid( 'search-form-' ) ); ?>
                                 <form role="search" method="get" action="">
                                    <label for="<?php echo $unique_id; ?>">
                                       <?php if (empty($image_all['alt'])) {
                                          $array1 = preg_split('/;|,/', $image_all['caption']);
                                          foreach( $array1 as $key1 => $captions ){ ?>
                                             <button value="<?php echo $captions; ?>" type="submit" id="<?php echo $unique_id; ?>" name="s"><?php echo $captions; ?></button>
                                             <?php echo ( ( $key1 < ( count( $array1 ) -1 ) ) ? '':'' );
                                          }
                                       } else {
                                          $array2 = preg_split('/;|,/', $image_all['alt']);
                                          foreach( $array2 as $key2 => $alt ){ ?>
                                             <button value="<?php echo $alt; ?>" type="submit" id="<?php echo $unique_id; ?>" name="s"><?php echo $alt; ?></button>
                                             <?php echo ( ( $key2 < ( count( $array2 ) -1 ) ) ? '':'' );
                                          }
                                       } ?>
                                    </label>
                                 </form>
                              </div>
                           <?php } ?>
                        <div id="fileName<?php echo $wp_query->current_post +1; ?>" style="display: none;"><?php echo $image_title['title']; ?></div>
                        <div class="buttons">
                           <button class="btn btn-light btn2 copy" id="btnCopy" rel="fileName<?php echo $wp_query->current_post +1; ?>" type="button" data-toggle="popover" title="copied" role="button" data-placement="2000"><i class="fas fa-clipboard-list"></i> Copy Photo ID</button>
                           <button id="btn_link" class="btn btn-light suggest" type="button" href="#" data-toggle="modal" data-target="#galleryModal<?php echo $wp_query->current_post +1; ?>" data-backdrop="static" data-keyboard="false">Suggest keywords/Larger Image</button>
                        </div>
                     </div>
                  </div>

                  <!-- Modal -->
                  <div class="modal fade" id="galleryModal<?php echo $wp_query->current_post +1; ?>" tabindex="-1" role="dialog" aria-labelledby="galleryModalLabel<?php echo $wp_query->current_post +1; ?>" aria-hidden="true">
                     <div class="modal-dialog modal-lg modal-dialog-centered">
                        <div class="modal-content">
                           <div class="modal-header">
                              <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                           </div>
                           <div class="modal-body d-flex h-100">
                              <div class="row justify-content-center align-self-center">
                              <div class="col-md-6" style="text-align: center;">
                                 <img src="<?php echo $atts[0]; ?>" class="img-fluid img-thumbnail">
                              </div>
                              <div class="col-md-6">
                                 <div class="row">
                                    <p class="entry-text"><strong>Photo ID:</strong> <?php echo $image_title['title']; ?></p>
                                    <?php if($image_all['caption'] || $image_all['alt']) { ?>
                                       <p class="entry-text"><strong>Keywords</strong></p>
                                       <div class="keywords">
                                          <?php if (empty($image_all['alt'])) {
                                             $array1 = preg_split('/;|,/', $image_all['caption']);
                                             foreach( $array1 as $key1 => $captions ){
                                          ?>
                                          <button value="<?php echo $captions; ?>" disabled><?php echo $captions; ?></button>
                                          <?php echo ( ( $key1 < ( count( $array1 ) -1 ) ) ? '':'' );
                                             }
                                       } else {
                                          $array2 = preg_split('/;|,/', $image_all['alt']);
                                          foreach( $array2 as $key2 => $alt ){
                                          ?>
                                          <button value="<?php echo $alt; ?>" disabled><?php echo $alt; ?></button>
                                          <?php echo ( ( $key2 < ( count( $array2 ) -1 ) ) ? '':'' );
                                          }
                                       } ?>
                                       </div>
                                    <?php } ?>
                                 </div>
                                 <div class="row" id="message">
                                    <?php echo do_shortcode( '[gravityform id="1" field_values="filename='. $image_title['title'] .'" ajax="true"]' ); ?>
                                 </div>
                              </div>
                           </div>
                        </div>
                        <div class="modal-footer">
                           <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                        </div>
                     </div>
                  </div>
               </div>
               <?php $c++; endwhile; ?>
            </div>
         </div>

         <?php ansel_pagination(); ?>
      </div>
   </main>
</div>

<?php if ( is_active_sidebar( 'sidebar' ) ) { ?>
   <div id="sidebar" class="col-md-2">
      <?php dynamic_sidebar('sidebar'); ?>
   </div>
<?php } ?>
</div>
</div>
</div>

<?php wp_reset_postdata();
get_footer(); ?>

Here's the pagination code from my functions file

// Numbered Pagination
if ( !function_exists( 'ansel_pagination' ) ) {
   function ansel_pagination() {

      global $wp_query;
      $current = max( 1, get_query_var( 'paged' ) );
      $links[] = ansel_archive_navigation_link( $current, 'current' );
      $total   = isset( $wp_query->max_num_pages ) ? $wp_query->max_num_pages : 1;
      $big = 999999999; // need an unlikely integer
      $translated = __( '', 'ansel' ); // Supply translatable string
         if( $total > 1 ) { ?>
            <div class="row justify-content-center">
               <div class="pagination_links" style="clear: both;">
                  Page: <?php echo paginate_links( array(
                     'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
                     'format' => 'page/%#%/',
                     'total' => $total,
                     'current' => $current,
                     'aria_current' => 'page',
                     'show_all' => false,
                     'end_size' => 3,
                     'mid_size' => 1,
                     'prev_next' => true,
                     'prev_text' => __( '&laquo; Previous' ),
                     'next_text' => __( 'Next &raquo;' ),
                     'type' => 'plain',
                     'add_fragment' => '',
                     'before_page_number' => '<span class="screen-reader-text">'.$translated.' </span>',
                     'after_page_number' => '',
                  ) ); ?>
               </div>
            </div>

            <div class="row justify-content-center">
               <form class="wpsp-page-nav-form" action="<?php echo esc_url_raw( get_pagenum_link($current) ); ?>" method="post" style="text-align: center;">
                  <div class="col-6 offset-3">
                     <label for="sortby" class="wpsp-label wpsp-hidden" style="display: inline-block;">Jump to</label>
                     <input class="wpsp-input-number" type="text" placeholder="page..."  size="15" name="page" style="display: inline-block; width: auto; background-color: #fff;"/>
                     <button class="btn" type="submit" style="display: inline-block;"><i class="fa fa-arrow-right" aria-hidden="true"></i></button>
                  </div>
               </form>
            </div>
         <?php }
      }
   }
   function ansel_archive_navigation_link( $page = false, $class = '', $label = '' ) {
      if( ! $page ) return;
         $classes = array( 'page-numbers' );
      if( !empty( $class ) ) $classes[] = $class;
         $classes = array_map( 'sanitize_html_class', $classes );
         $label = $label ? $label : $page;
         $link = esc_url_raw( get_pagenum_link( $page ) );
      return ?><a class="<?php join('', $classes); ?>" href="<?php echo $link; ?>"><?php echo $label; ?></a><?php ;
   }

And my search page:

<?php
/**
* The template for displaying search results pages
*
* @link https://developer.wordpress.org/themes/basics/template-hierarchy/#search-result
*
* @package WordPress
* @subpackage ansel
* @since 1.0
* @version 2.0
*/

get_header(); ?>

<div id="ajax-load">

   <div id="Search" <?php post_class(''); ?>>
      <div class="content container-fluid" style="padding: 0 !important;">
         <div class="row justify-content-center">
            <div class="col-md-9">
               <h1 class="header__title">
                  <i class="fas fa-map-marker-alt"></i>
                  <?php if (have_posts()) { printf( __( 'Search Results for: %s', 'ansel' ), get_search_query() ); } else { ?>Nothing Found<?php } ?>
               </h1>

               <main>
                  <div class="container-fluid">
                     <div class="alert alert-info" role="alert" style="width: 100%;">
                        Number of Results <span class="badge badge-light"><?php echo $wp_query->found_posts; ?></span>
                     </div>

                     <div class="row justify-content-center">
                        <div class="container-fluid">

                           <?php if ( have_posts() ) :
                              $pagenum = $wp_query->query_vars['paged'] < 1 ? 1 : $wp_query->query_vars['paged'];
                              $first = ( ( $pagenum - 1 ) * $wp_query->query_vars['posts_per_page'] ) + 1;
                              $last = $first + $wp_query->post_count - 1;
                              echo "Showing posts $first - $last of $wp_query->found_posts";

                              ansel_pagination();

                           else : ?>
                              <p><?php _e( 'Sorry, but nothing matched your search terms. Please try again with some different keywords.', 'ansel' ); ?></p>
                           <?php endif;

                           if ( have_posts() ) : ?>
                              <div class="grid">
                                 <div class="grid-sizer"></div>
                                 <?php /* Start the Loop */
                                 $i = 1;

                                 while (have_posts()): the_post();
                                    $item = get_the_id();
                                    $atts = wp_get_attachment_image_src($item, 'medium_large');
                                    $url = strtok($atts[0], '?');
                                    $atts_full = wp_get_attachment_image_src($item, 'full');
                                    $image_all = wp_prepare_attachment_for_js($item);
                                    $attachment_page = wp_get_attachment_url( $item );
                                    $title = wp_prepare_attachment_for_js($item);
                                    $image_title = wp_prepare_attachment_for_js($item);
                                    $img = $atts_full[0];

                                    <div class="grid-item">
                                       <div class="watermark"><img id="image<?php echo $i; ?>" src="<?php echo $url; ?>" alt="<?php echo $image_all['alt']; ?>"></div>
                                    </div>
                                 <?php $i++; endwhile; ?>
                              </div>
                           <?php endif; ?>
                        </div>

                        <?php ansel_pagination(); ?>

                     </div>
                  </div>
               </main>
            </div>
         </div>
      </div>
   </div>
</div>

<?php get_footer();
6
  • 1
    Your pagination issue on your taxonomy page, is because pagination goes off of the main query, but you're using a secondary query. So the pagination is for the wrong query. Ditch the custom WP_Query and replace it with pre_get_posts – Tom J Nowell Mar 25 '20 at 15:56
  • I see ajax-load, are you using normal page loading or are you doing some javascript trickery to AJAX in each page? – Tom J Nowell Mar 26 '20 at 9:41
  • Noting I found this question at stackoverflow.com/questions/60604222/… It appears this question has little to do with how to use pre_get_posts ( X Y question, it looks like pre_get_posts was meant to be a solution ) – Tom J Nowell Mar 26 '20 at 9:45
  • I don't have a problem with pagination on the taxonomy page. That works just fine. My problem is on the search results page. – Laura Sage Mar 31 '20 at 13:12
  • And I had asked that question several weeks ago, looking for some assistance. There have been no replies, so I kept searching and keep seeing mentions of needing to use pre_get_posts. Thus my question about that specifically. – Laura Sage Mar 31 '20 at 13:13
0

pre_get_posts happens just before a WP_Query needs to go to the database to grab stuff. Since every page has a main query, that can be changed.

Does it go in the search template?

No! By the time templates are loaded, the main query has already decided what to grab and gone to the database. Newcomers usually think the template determines the posts, but it's actually the other way around! The query runs, then the query is used to figure out if we should load page.php or archive.php etc.

When you call functions like is_search or is_single, it's actually asking the main query. So, it's too late if it's in the template.

This means that to use pre_get_posts, you have to use it in:

  • plugins
  • functions.php
  • On hooks that happen before the main query runs

Because the query is what determines which type of template is shown, you can actually mess with the query variables to change that.

Additionally, you might be wondering where it gets the values from to begin with, they come from the rewrite rules:

  1. example.com/hello-world
  2. example.com/index.php?name=hello-world
  3. new WP_Query( [ 'name' => 'hello-world' ] )
  4. pre_get_posts
  5. Use query object and see that it's a single post a. Try to load single-hello-world.php b. Try to load single.php c. etc...

Also, does it work differently when I'm querying a taxonomy archive page?

Yes and no. Remember that pre_get_posts runs for all queries. Not just the main query, but widget queries, RSS, REST API, admin area, etc.

This means, if you use the filter, you can't just set options, as they'll apply site wide. You have to specifically check you're on the query and page you desire.

So How Do I Use pre_get_posts?

Here's an example from the official docs that sets the movies post type archive to 50 posts per page:

function hwl_home_pagesize( $query ) {
    if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'movie' ) ) {
        // Display 50 posts for a custom post type called 'movie'
        $query->set( 'posts_per_page', 50 );
        return;
    }
}
add_action( 'pre_get_posts', 'hwl_home_pagesize', 1 );

But that's not built super great, so lets use an improved version:

function hwl_home_pagesize( \WP_Query $query ) {
    if ( is_admin() ) {
        return; // we want the frontend! exit if it's WP Admin
    }
    if ( !$query->is_main_query() ) {
        return; // we want the main query!
    }
    if ( ! is_post_type_archive( 'movie' ) ) {
        return; // we only want the movie archives
    }
    // On the movie archive, show 50 posts
    $query->set( 'posts_per_page', 50 );
}

add_action( 'pre_get_posts', 'hwl_home_pagesize', 1 );

Notice that we do checks first to make sure we're only setting the posts_per_page when we want. For a search page, you might check $query->is_search(), etc

What If My Template Uses a WP_Query?

If your template ignores the main loop, and uses its own instead, then stop doing that. Use pre_get_posts to change what the main loop shows instead.

Note, that you can modify these queries with pre_get_posts, but, is_main_query will be false, and you'll need to add specialised code to target that specific query, otherwise everything from widgets to nav menus might be impacted

10
  • Thank you. A lot of that is making some sense. While you were giving me this great answer, I had also decided it may be useful to have my code entered and so that's all been entered above. Wondering if there's anything about what you explained above that I should be keeping in mind with what I already have in my code? – Laura Sage Mar 25 '20 at 15:16
  • I have tried adding the 2nd version you posted above, and it hasn't solved my issue on the search page, so I'm guessing there's something within the code I posted above that's causing this. – Laura Sage Mar 25 '20 at 15:27
  • @LauraSage neither of my code examples are copy paste solutions, they don't even reference search pages, they're intended to demonstrate the usage of the filter in the general case – Tom J Nowell Mar 25 '20 at 15:51
  • Ok. Then I guess I'm still somewhat confused. Here's what I did: function ansel_queries( WP_Query $query ) { if ( is_admin() ) { return; // we want the frontend! exit if it's WP Admin } if ( !$query->is_main_query() ) { return; // we want the main query! } if ( ! is_post_type_archive( 'mediacat' ) ) { return; // we only want the movie archives } // On the mediacat archive, show 21 posts $query->set( 'posts_per_page', 21 ); } add_action( 'pre_get_posts', 'ansel_queries', 1 ); – Laura Sage Mar 25 '20 at 15:53
  • But mediacat isn't a post type archive, it's a taxonomy term archive. Code blocks don't work in comments – Tom J Nowell Mar 25 '20 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.