0

I know this question has been asked many times, and I've been trying every answer I came across all day from 11am-9pm and I am STUCK.

Here is my search page http://tribute-software.com/development/?s=1991

As you can see the search right now is for 1991. I have some data printed on the page so it can help us debug. It is showing the correct 10 posts in the printed data, and it calculates the correct number of pages (2) -- (I set my posts per page to 4 in the backend).

I cannot get any results when I click page 2. BUT when I search for a name "Danielle" for example, then the page 2 works. I've rewritten so many things in my template and came to realize that it will only display page 2 results if my search is coming from the post_title.

Let me know if anything is obvious by looking at page. I will post the code below:

global $wp_query; /*were only keeping this so we can grab the s variable*/
//$numPostsFound =  $wp_query->found_posts;

/*'s' is what the user typed in the search bar*/
$string = $wp_query->query['s'];

//adhere to paging rules
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; 

//Get all 'fallen_hero' posts to start
$args = array(
    'post_type'     => 'fallen_hero',
    'meta_key'      => 'hero_last_name',
    'meta_type'     => '',
    'orderby'       => 'meta_value',
    'order'         => 'ASC',
    'post_status'   => 'publish',
    'posts_per_page' => -1,
);
$origPosts = new WP_Query( $args );

$posts1 = $origPosts->get_posts();
$ids = []; //array to store the id's of the wanted posts

/*Go through each post and check*/
foreach($posts1 as $post) {
    setup_postdata( $post );

    $classDate = get_field('class'); //search if it matches class date
    $fullName = $post->post_title; //search if it matches post title

    //if its a match to one of the 2, add the ID to the array
    if((stripos($fullName, $string) > -1) || $classDate == $string){
        $ids[] = $post->ID;
    }

}
wp_reset_postdata();

if (!empty($ids)) { //search the array of good IDs
    /*make new query with the right IDs - need to do this to make pagination work*/
    $args = array(
        'post__in'      => $ids,
        'post_type'     => 'fallen_hero',
        'meta_key'      => 'hero_last_name',
        'meta_type'     => '',
        'orderby'       => 'meta_value',
        'order'         => 'ASC',
        'post_status'   => 'publish',
        'paged'         => $paged,
    );
    $results = new WP_Query( $args );

    print_r($results);


    //this is for the pagination at the bottom
    $numPostsFound = count($ids);

and then in the same template

if ( function_exists('html5wp_cpt_pagination') ) {
    html5wp_cpt_pagination($results, $numPostsFound);
}

and finally my custom-post-type pagination (written by someone else before me)

function html5wp_cpt_pagination($cpt_query, $numPostsFound){
    $big = 999999999;

    if($cpt_query->max_num_pages){
        $maxpages = $cpt_query->max_num_pages;
    }else{
        //$maxpages= 20;
        //echo $numPostsFound;
        $maxpages = ceil($numPostsFound/get_option( 'posts_per_page' ));
    }

    $paginate = paginate_links( array(
        'base' => str_replace($big, '%#%', get_pagenum_link($big)),
        'type' => 'array',
        'format' => '?paged=%#%',
        'current' => max(1, get_query_var('paged')),
        'total' => $maxpages,
        'prev_text' => __('«'),
        'next_text' => __('»'),
    ));


    if ($maxpages > 1) : ?>
<ul class="pagination">
    <?php foreach ( $paginate as $page ) {
    echo '<li>' . $page . '</li>';
    } ?>
</ul>
<?php
    endif;
}

EDIT STEPS -> 1) get the 's' variable from the main query (search query) so we can compare it to our custom post type

2) get all fallen_heroes post types (yes i know I can search for meta values in this part but I tried to extend it because it didnt work that way)

3) from the posts collected above, search if the 's' string matches the field 'class' (for class date) or if it matches the name of the person (which in this case I use post_title)

4) add all matches to an id[] array so we can keep track

5) finally, query for all fallen_hero post types with the array of ids, but also with $paged because we need it paged here.

7
  • whether or not a page is a 404 is determined by the results of the main query, that's how WordPress is able to serve the 404.php template. whatever results you get in queries in the template are irrelevant.
    – Milo
    Oct 4, 2018 at 2:46
  • So, just to understand this correctly: you want to use the search function to add a custom field to be searched in? Oct 4, 2018 at 8:35
  • Milo - I know but I don't know how to see whats happening exactly before the 404 arrives.
    – danielle
    Oct 4, 2018 at 12:45
  • @kuchenundkakao yes. I just added a few more comments to the top code, and I added a little more explanation at the very bottom of my post
    – danielle
    Oct 4, 2018 at 12:46
  • @danielle I saw that your page is redirecting to main search page rather than a 404.php It's actually going to a post type archive called fallen_heros. May be you need a search.php file
    – bagpipper
    Oct 4, 2018 at 16:36

1 Answer 1

1

Rather than try to wrestle with the default search query, I would take a different approach and create a custom search function.

First, we add a new custom search query var, in this case search_var. Then we add a couple of rewrite rules so we can have URLs like:

http://example.com/custom-search/1991/
http://example.com/custom-search/1991/page/2/

with this function:

function wpd_custom_search_rules() {
    add_rewrite_tag(
        '%search_var%',
        '([^/]+)'
    );
    add_rewrite_rule(
        'custom-search/([^/]+)/?$',
        'index.php?post_type=fallen_hero&search_var=$matches[1]',
        'top'
    );
    add_rewrite_rule(
        'custom-search/([^/]+)/page/?([0-9]{1,})/?$',
        'index.php?post_type=fallen_hero&search_var=$matches[1]&paged=$matches[2]',
        'top'
    );
}
add_action( 'init', 'wpd_custom_search_rules' );

Don't forget to flush rewrite rules after adding these. You'll also need to update your search form to use this new query var/pattern.

The above rules just set up basic Main Queries for our post type, which WordPress will identify basically as Post Type Archives.

The next step is to alter those main queries to give us the posts we want. You could just paste most of your existing query code in here, and pass the resulting array of IDs to the main query:

function wpd_custom_search_query( $query ) {
    if ( isset( $query->query['search_var'] ) ) {
        // your custom query code would go here
        $post_ids = [23,42,66];
        $query->set( 'post__in', $post_ids );
    }
}
add_action( 'pre_get_posts', 'wpd_custom_search_query', 10, 2 );

You don't have to worry about pagination, as that happens automatically now. If you want a particular template for these that's different from the post type archive template, you can filter the template hierarchy and inject a new one. Just check if get_query_var('search_var') contains something to know that you are serving one of these search requests.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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