Custom query form submission pagination

There is a question very similar to mine, which can be found here. The difference with my question is: my search form is on several pages (page.php and single.php) and I don’t use wp-pagenavi. I’ve tried the suggested solutions posted there but they didn’t work.

What is working

Read More
  • The query displays the right results
  • The query displays the right results after form submission
  • Pagination shows with the correct links (ie example.com/overview/?paged=2 and example.com/city/boston/?paged=2)
  • Pagination with the same settings works on search.php

What is not working: if I submit the form and click on any page but page 1 the URL does become example.com/overview/?paged=2 or example.com/city/boston/?paged=2 but no results are displayed.

Updated after the accepted answer:
Please read the notes in the code to see how the problem was solved.

— Below here the setup of my code

On page.php

if(is_page('overview')) {
    get_template_part('templates/overview', 'main');
}

On single.php (include the same file)

if(is_singular('cities')) {
    get_template_part('templates/overview', 'main');
}

On overview-main.php

include_once 'overview-search-input.php'; 
include_once 'overview-sidebar.php';

On overview-search-input.php (changed after UPDATE 3, original code below here)

   if(!empty($_GET['period'])) {
        $period = $_GET['period'];
   }
   else {
        $period = 'upcoming'; // Set to upcoming if nothing is selected
   }

   $query = search_v1($period, $paged); // Passing the $paged parameter in the query

   $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; // The $paged parameter

On overview-sidebar.php

<form action="<?php echo get_permalink(); ?>" method="get"> 
<select name="period" placeholder="Select">
  <option value=""></option>
  <option value="all"></option>
  <option value="upcoming"></option>
</select>
</form>

in the function search_v1:

    $args = array(
        'post_type'         => 'events',
        'post_status'       => 'publish',
        'posts_per_page'    => 20,
        'paged'             => $paged, // This was passed into the function
        'meta_query'        => array($meta_query), // This is generated based on the $period input and it's working (tested)
        'meta_key'          => 'date_from',
        'orderby'           => 'meta_value',
        'order'             => 'ASC',
    );

    return new WP_Query($args);

Then on overview-main.php

   if($query->have_posts()): while ($query->have_posts()): $query->the_post();
      // Do stuff
    endwhile;

    create_pagination($query);

    wp_reset_postdata();
    endif;

And in the function create_pagination:

$query->query_vars['paged'] > 1 ? $current = $query->query_vars['paged'] : $current = 1;

$args = array(
    'base' => @add_query_arg('paged','%#%'),
    'format' => '?paged=%#%',
    'total' => $query->max_num_pages,
    'current' => $current,
    'show_all' => false,
    'end_size' => 1,
    'mid_size' => 2,
    'prev_next' => true,
    'prev_text' => '<i class="icon-chevron-left"></i>',
    'next_text' => '<i class="icon-chevron-right"></i>',
    'type' => 'list'
);

return paginate_links($args);

The problem was: Since both pagination functions work and display the correct pagination links I assume that’s not the problem. I think it lies in the custom query (since this pagination works on search.php when the results are generated once and not altered by form input).

The problem was solved: by using the ‘paged’ parameter and passing it into the query

Related posts

2 comments

  1. There are some things that should be changed in your code:

    1. Please no not use $_SESSION stuff. So do not add session_start anywhere. You can pass the current state via the query string, using method="get" in your form.
    2. For a better flow, you can pass the current page to search_v1 function as argument, in this way you are sure will be not errors
    3. When you have to access superglobals array, instead of accessing directly is recomned to use filter_input
    4. in the overview-search-input.php file, last line is $query = search_v1($_SESSION['period']); that is completely useless
    5. I think is useful in the form select the period option of the current showed posts, e.g. when you are viewing posts for period ‘upcoming’, in the form should be selected the option ‘upcoming’.

    Applying this changes:

    • page.php and single.php and stay unchanged.
    • remove session_start(); from where you have added

    Then

    overview-search-input.php

    <?php
    $period = filter_input(INPUT_GET, 'period', FILTER_SANITIZE_STRING);
    $paged = get_query_var('paged');
    if ( empty($period ) ) $period  = 'upcoming';
    if ( empty($paged) ) $paged = 1;
    

    overview-sidebar.php

    <form action="<?php echo get_permalink(); ?>" method="get">
    <select name="period" placeholder="Select">
      <option <?php selected('', $period) ?>></option>
      <option <?php selected('all', $period) ?>>all</option>
      <option <?php selected('upcoming', $period) ?>>upcoming</option>
    </select>
    </form>
    

    overview-main.php

    include_once 'overview-search-input.php';
    include_once 'overview-sidebar.php';
    
    $query = search_v1( $period, $paged );
    
    if( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post();
      // Do stuff
    endwhile;
    
    echo create_pagination( $query, $period );
    
    wp_reset_postdata();
    endif;
    

    Finally the 2 functions, search_v1 and create_pagination:

    function search_v1( $period = 'upcoming', $paged = 1 ) {
      if ( empty($paged) ) $paged = 1;
      $meta_query = array(
        // create your meta query here
      );
      $args = array(
        'post_type'         => 'events',
        'post_status'       => 'publish',
        'posts_per_page'    => 20,
        'paged'             => $paged,
        'meta_query'        => array($meta_query),
        'meta_key'          => 'date_from',
        'orderby'           => 'meta_value',
        'order'             => 'ASC',
      );
      return new WP_Query( $args );
    }
    
    
    function create_pagination( $query, $period = 'upcoming' ) {
      $current = isset($query->query_vars['paged']) ? $query->query_vars['paged'] : 1;
      $args = array(
        'base' => get_permalink() . '%_%',
        'format' => '?paged=%#%&period=' . $period,
        'total' => $query->max_num_pages,
        'current' => ($current > 0) ? $current : 1,
        'show_all' => false,
        'end_size' => 1,
        'mid_size' => 2,
        'prev_next' => true,
        'prev_text' => '<i class="icon-chevron-left"></i>',
        'next_text' => '<i class="icon-chevron-right"></i>',
        'type' => 'list'
      );
      return paginate_links($args);
    }
    
  2. Instead of this line

    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    

    Can you use this and check.

    $paged = (get_query_var('page')) ? get_query_var('page') : 1;
    

    Also this

    $query->query_vars['paged'] > 1 ? $current = $query->query_vars['paged'] : $current = 1;
    

    to

    $query->query_vars['page'] > 1 ? $current = $query->query_vars['page'] : $current = 1;
    

    Note: As you are using custom page templates, “paged” doesn’t work there.

Comments are closed.