How to use pre_get_posts

时间:2020-03-25 作者:Laura Sage

我有点搞不懂这个钩子是怎么用的。它是在搜索模板、存档页中还是在函数中?它是否围绕分页代码?此外,当我查询分类法归档页面时,它的工作方式是否有所不同?

我想我也可以把我所有的代码都包括在这里。除了分页问题外,其他一切都正常工作,这取决于您是否在存档页面上,或者您是否在该页面上进行了搜索。

目前最大的问题是搜索结果页面。它很好地显示了分页链接。但是,当您单击任何页码时,它会更改为URL中正确的页码,但结果不会更改。

第二个问题是,在实际的归档页面上,单击编号的分页链接效果很好。我获取urlhttp://www.domain.com/imagetags/library/page/57/ 例如。然后,如果我在跳转框中输入页码(比如23),它会将我带到正确的位置,但使用此URL-http://www.domain.com/imagetags/library/page/57/?page=23

到目前为止,一切都很好。但是,如果从跳转到链接I,然后再次单击其中一个编号的分页链接,它将更改/页/25/但是因为/?页面=23保留,显示的图像根本没有更改。当然有办法让跳转框与分页链接使用相同的URL吗?

不过,我最迫切需要修复的部分是搜索结果页面。不过我假设,修复这个问题可能也会修复我的分类页面(希望如此)。

提前谢谢。

这是我的分类页面:

<?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(); ?>
这是我的函数文件中的分页代码

// 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 ;
   }
和我的搜索页面:

<?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();

1 个回复
SO网友:Tom J Nowell

pre_get_posts 发生在WP_Query 需要去数据库拿东西。因为每个页面都有一个主查询,所以可以更改。

它是否在搜索模板中?

不加载模板时,主查询已经决定要获取什么并转到数据库。新手通常认为模板决定了帖子,但实际上恰恰相反!查询运行,然后使用查询确定是否应该加载page.phparchive.php

调用以下函数时is_searchis_single, 它实际上是在问主要的问题。所以,如果它在模板中,那就太晚了。

这意味着要使用pre_get_posts, 您必须在以下情况下使用它:

插件functions.php

  • 在主查询运行之前发生的挂钩上,因为查询决定显示哪种类型的模板,所以实际上可以通过修改查询变量来更改它。

    此外,您可能想知道这些值从何处开始,它们来自重写规则:

    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. 使用查询对象并查看它是一个单独的posta。尝试加载single-hello-world.phpb、 尝试加载single.phpc、 等等
    另外,当我查询分类法归档页面时,它的工作方式是否有所不同?

    是和否。记住这一点pre_get_posts 运行时间all 查询。不仅仅是主查询,还有小部件查询、RSS、REST API、管理区域等。

    这意味着,如果您使用过滤器,您不能只设置选项,因为它们将应用于整个站点。您必须特别检查您是否在所需的查询和页面上。

    那么我如何使用pre_get_posts?

    以下是官方文档中的一个示例,它将电影帖子类型存档设置为每页50篇帖子:

    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 );
    
    但这并不是构建得非常好,所以让我们使用一个改进的版本:

    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 );
    
    请注意,我们首先进行检查,以确保只设置posts_per_page 当我们想要的时候。对于搜索页面,您可以检查$query->is_search(), 等

    如果我的模板使用WP_Query?

    如果模板忽略了主循环,而使用了自己的循环,那么请停止这样做。使用pre_get_posts 更改主循环显示的内容。

    请注意,您可以使用修改这些查询pre_get_posts, 但是is_main_query 将是false, 您需要添加专门的代码来针对特定的查询,否则从小部件到导航菜单的所有内容都可能会受到影响