0

I'm so confused with this. I made a universal template for all achrive for my CPT.

functions.php:

add_filter( 'template_include', 'wpsites_cpt_archive_page_template', 99 );
/**
 * @author    Brad Dalton
 * @example   http://wpsites.net/
 * @copyright 2014 WP Sites
 */
function wpsites_cpt_archive_page_template( $template ) {

    if ( is_post_type_archive(array( drzewa_formowane, pre_bonsai ) ) ) {
        $new_template = locate_template( array( 'archive-cpt.php' ) );
        if ( '' != $new_template ) {
            return $new_template ;
        }
    }

    return $template;
}

and my loop in archive-cpt.php:

<div class="center">
                    <?php
                    $current_post_type = get_post_type();
                    // Define custom query parameters
$custom_query_args = array(
    'post_type'     => $current_post_type,
    'post_status'   => 'publish',
    'meta_key'      => 'order',
    'orderby'       => 'meta_value_num',
    'order'         => 'asc',
    'posts_per_page'=> '1'
);
// Get current page and append to custom query parameters array
$custom_query_args['paged'] = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
// Instantiate custom query
$custom_query = new WP_Query( $custom_query_args );
// Pagination fix
$temp_query = $wp_query;
$wp_query   = NULL;
$wp_query   = $custom_query;
// Output custom query loop
if ( $custom_query->have_posts() ) :
    while ( $custom_query->have_posts() ) :
        $custom_query->the_post(); ?>
                        <?php include 'product.php' ?>
                        <?php endwhile;
endif;
// Reset postdata
wp_reset_postdata(); ?>
                        <nav class="pagination">
                            <?php
$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' => $wp_query->max_num_pages,
    'prev_next'          => true,
    'prev_text'          => __(' « '),
    'next_text'          => __(' » '),
    'type'               => 'plain',
) ); ?>
                        </nav>
                        <?php
// Reset main query object
$wp_query = NULL;
$wp_query = $temp_query;
                    ?>
                </div>

and it's works besides pagination. When I use 'posts_per_page' value smaller than 'Blog pages show at most' in Dashboard, paginations shows right numbers of pages but every links redirects to 404. So it seems like this: pagination works based on 'Blog pages show at most' from Dashboard but shows page numbers based on 'posts_per_page'. So where's bug? I made this loop based on this post: How to fix pagination for custom loops?

  • 2
    Don't create a query in the template, use pre_get_posts to alter the main query. – Milo Mar 18 '18 at 0:43
  • But why? What's wrong with WP_Query? I need add some paramets like order etc. In "The Loop" article in WP Codex they use in exemples WP_Query for more complicated loops. – Damian Mar 18 '18 at 0:49
  • 1
    The number of pages in an archive depends on the main query, whether or not it's a 404 is decided before the template gets loaded. You can alter query parameters with pre_get_posts, the important part is when this code runs- before the main query, so pagination will work correctly. – Milo Mar 18 '18 at 0:55
  • I see. I will try it and keep posted how it's going, thanks. – Damian Mar 18 '18 at 0:59
  • do your query in your functions.php file then call your function in the template. – Nathaniel Flick Mar 18 '18 at 1:08
1

Ok. So thanks to @Milo I figure out it how it should be done. First of all in archive should be a standard loop. Then in functions.php I just add a pre_get_posts function directly for archive pages and it's look like this:

archive-cpt.php loop:

<div class="center">
                    <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
                    <?php include 'product.php' ?>
                    <?php endwhile ?>
                    <nav class="pagination">
                        <?php
    $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' => $wp_query->max_num_pages,
    'prev_text'          => __(' « '),
    'next_text'          => __(' » '),
) );
    ?>
                    </nav>
                    <?php else : ?>
                    <p>
                        <?php esc_html_e( 'Sorry, no posts matched your criteria.' ); ?>
                    </p>
                    <?php endif; ?>
                </div>

and in functions.php:

function archive($query) {
  if ( !is_admin() && $query->is_main_query() ) {
    if ($query->is_archive) {
      $query->set('post_status', 'publish');
      $query->set('meta_key', 'order');
      $query->set('orderby', 'meta_value_num');
      $query->set('order', 'asc');
    }
  }
}

add_action('pre_get_posts','archive');

The point is do not create a new WP_Query but modifying existing. Then pagination and others functionality works fine. In pre_get_posts we can also add additional parameters to loop like 'order' etc using

$query->set('order', 'asc');

now everything is working.

Here's a usefull links about: https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

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.