3

I've got several search forms on my site and I want them to show different results. My website has a very strict hierarchy and the search form on a parent site should only show results from it's child pages.

My plan was to include different hidden fields on the different parent pages which contain the id of that particular page. In the search.php I then wanted to process the results and filter out the pages and posts that have no relation to the parent page.

Is there an easy way on how to achieve this?

Thanks in advance.

EDIT 1


This is my search.php

<?php 
if (have_posts()){
  while(have_posts()){
    the_post(); ?>
    <div>
      <h4><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
      <p><?php echo get_the_author(); ?> - <?php echo get_the_date(); ?></p>
      <p><?php echo get_the_excerpt(); ?></p>
    </div>
    <?php
  }
} else{ ?>
  <h3>Sorry</h3>
  <p>We are sorry but we could not find any matching articles on our site. Please try again with an other search request.</p>
  <?php
    get_search_form ();
}
?>

And the searchform.php:

<form role="search" method="get" id="searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>">
  <label>Search...</label>
  <input type="text" name="s" id="s" value="<?php echo get_search_query(); ?>" placeholder="Search..." />
  <input type="hidden" name="post_parent" value="<?php echo (int)get_the_ID(); ?>" />
  <button type="submit"><i class="fa fa-search" aria-hidden="true"></i></button>
</form>

EDIT 2

I also added <?php wp_reset_query(); ?> before the if(have_posts()){}. This results in no change. The pages are still shown.

1
  • You should only use wp_reset_query to clean up after query_posts calls, I recommend avoiding both
    – Tom J Nowell
    Jul 5, 2016 at 16:49

2 Answers 2

1

You can use pre_get_posts filter to filter out what you need. There's an example on how to do this in Codex:

https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts#Exclude_Pages_from_Search_Results

function search_filter($query) {
  if ( !is_admin() && $query->is_main_query() ) {
    if ($query->is_search) {
      $query->set('post_type', 'post');
    }
  }
}

add_action('pre_get_posts','search_filter');

Also, this article might get you in the direction of editing the search form...

7
  • Unfortunately I don't get the idea, on how to use this for my problem. How do I exclude every post except the ones that have a relation to the site of the search form?
    – Sam
    Jul 4, 2016 at 16:54
  • You should pass the ID of the parent post to the search, than search for the post children, and than do $query->set('post__in', $children_ids);, where $children_ids is an array containing the ID's you're looking for.. Jul 4, 2016 at 17:03
  • This also affects the normal catching of the posts... How do I delimit this to search requests from users?
    – Sam
    Jul 4, 2016 at 17:39
  • In the code example I posted there's if ($query->is_search) - that limits anything you do inside to just the search queries... Jul 4, 2016 at 18:52
  • This is a response to user1049961 <hr> Thanks for your feedback. Unfortunately, I don't really get it working... I included this code to my functions.phpand tested it out. There are still results shown which have a different parent. $children_ids = get_children( $args ); $args = array( 'post_parent' => $_GET['pageID'], 'post_type' => 'any', 'numberposts' => -1, 'post_status' => 'publish' ); function search_filter($query) { if ( ! is_admin() && $query->is_main_query() ) { if ( $query->is_search() ) { $query->set('post__in', $children_ids); } } } add_action('pre_get_posts','search_filter')
    – Sam
    Jul 4, 2016 at 22:50
0

While the pre_get_posts filter is going to let you modify the main query before it happens, letting you add extra requirements, in this case it isn't necessary! You can do it all with the URL and the search form

First, the query variables passed into WP_Query can be used in the URL. post_parent being the query var you're wanting.

So if we have this:

<form action="/" method="get">
    <input type="text" name="s" />
    <input type="hidden" name="post_parent" value="<?php echo (int)get_the_ID(); ?>"/>
    <input type="hidden" name="post_type" value="page"/>
</form>

Then any search results will be limited to those whose post_parent is the page that the search came from. You'll see URLs such as /?s=test&post_parent=123.

This trick can be used to filter by categories and authors, for example, searching a category:

/category/example/?s=test

Only showing posts by a particular author in a date archive:

/2016/?author=123

13
  • I just implemented your code snippet, but it does not work. I still get sites from different parents.
    – Sam
    Jul 4, 2016 at 23:26
  • Do you replace or modify the main query/loop in your search.php? Any signs of query_posts or WP_Query? If you have enough subpages that you need to search them, perhaps you should be using a custom post type or a custom taxonomy instead of hacking things into parent and child pages
    – Tom J Nowell
    Jul 5, 2016 at 9:13
  • No, I don't think so. I added an edit to the question which shows the search.php as well as the searchform.php.
    – Sam
    Jul 5, 2016 at 12:24
  • @Chwebo I realise now, you're searching inside pages not posts, I've added a post_type field. Keep in mind that none of these solutions will handle sub-sub-pages, and grandchild pages, if you want those then your search query is going to become significantly slower/more expensive, and the code will become a lot more complex and difficult
    – Tom J Nowell
    Jul 5, 2016 at 16:52
  • Well... I do want to include all the pages. My hierarchy is like the following: Parent Page 1 - Parent Page 2 - Parent Page 3 - Content Page. Is there a plugin to achieve this or is it extremely hard to hand-code it by myself?
    – Sam
    Jul 5, 2016 at 17:01

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.