Search result based on menu category
-
Hi All,
i’m looking for two pieces of code that can help me with the following:
I got posts and pages with a custom menu. These posts/pages got a custom template activated. The templates contains the menu for the specific posts and pages. This way i can order pages/posts in two different categories.
Now i like to change the search function; the search output should be based on the active custom menu category.
I named menu 1: Benelux and menu 2: International
1: First peace of code needs to be for the searchform.php
The code should look at the current active menu(category) and the search result should be based on the active menu.If the menu is for example “Benelux” then the search result should only display pages/posts from the custom taxonomy that i made <input type=”hidden” name=”location” value=”benelux” />
Or if the active menu is “International” then display pages/posts from the custom taxonomy <input type=”hidden” name=”location” value=”international” />I found the following code to get the menu category…not sure if this is useful..
(wp_nav_menu( array( 'menu' => 'benelux' ) )
2: Second peace of code is needed for the search.php (header).
Because if the output should work correctly than we also need to change the menu for this search result page. Default the search.php uses the main menu.So the following code needs to see if the pages/post contain taxonomy benelux or international and change the menu accordingly.
It would just be really awesome if this is possible.
Greatings,
Taro
-
?? And the ‘query_vars’ filter hook you added is still active?
If so, there’s a problem with the rewrite rule. Did you do the following procedure from the Codex?IMPORTANT: Do not forget to flush and regenerate the rewrite rules database after modifying rules. From WordPress Administration Screens, Select Settings -> Permalinks and just click Save Changes without any changes.
If you’ve done all of that, I’m running out of ideas. It’s not that our general approach is wrong, it’s just that there’s some detail wrong that I cannot identify.
One last idea… let’s change the priority of the added rewrite rules hook to 0 so your rules are checked first:
add_action('init', 'custom_select_region', 0 );
Did not work.
I still have this code in the function.php
function query_vars($query_vars) { $query_vars[] = 'region'; return $query_vars; } add_filter('query_vars', 'query_vars');
But must i change it to?:
function custom_select_region_query_vars($query_vars) { $query_vars[] = 'region'; return $query_vars; } add_filter('query_vars', 'custom_select_region_query_vars');
I also got this code in function now:
function custom_select_region() { add_action('init', 'custom_select_region', 0 ); add_rewrite_rule('^([^/]*)/([^/]*)/?','index.php?pagename=$matches[2]®ion=$matches[1]','top'); add_rewrite_rule('^([^/]*)/([^/]*)/([0-9]{1,})/?','index.php?pagename=$matches[2]®ion=$matches[1]&paged=$matches[3]','top'); } add_action('init', 'custom_select_region');
and this in the search form:
<?php global $wp_query; $region = $wp_query->is_main_query()? $wp_query->get('region') :''; echo "<input type='hidden' name='region' value='$region' />"; ?>
and this on the test page “sample”:
<?php $args = array(); if ( array_key_exists('s', $_POST )){ $args = array( 's' => $_POST['s'], );} if ( array_key_exists('region', $_POST )) $args['category_name'] = $_POST['region']; $posts = get_posts( $args ); ?>
i disabled the var_dump for the moment.
You don’t need to change the ‘query_vars’ callback name, but it wouldn’t hurt. There’s no reason a function cannot be named the same as a filter hook name, but I think it’s slightly confusing to do so. Others probably think it is more clear, but I rarely see anyone doing it.
Please change the rewrite hook like this:
function custom_select_region() { add_rewrite_rule('^([^/]*)/([^/]*)/?','index.php?pagename=$matches[2]®ion=$matches[1]','top'); add_rewrite_rule('^([^/]*)/([^/]*)/([0-9]{1,})/?','index.php?pagename=$matches[2]®ion=$matches[1]&paged=$matches[3]','top'); } add_action('init', 'custom_select_region', 0 );
I’ve come to the realization that I’ve been addressing little details without a good grasp of the overall situation. Time to take a step back and make sure I understand what you’re trying to do as a test with the sample page.
I’m assuming you begin the test with requesting
your-domain.tld/benelux/sample/
If so, checking for things in
$_POST
is pointless because we made a GET request. Thusget_posts()
would just return what it does by default, a page’s worth of posts regardless of category. It seems to me you should be checking for$_GET['region']
on sample to get posts in the Benelux category, assuming the rewrite rules are working.If that much works with using
$_GET
, then going to the next page is the next test. The link should beyour-domain.tld/benelux/sample/2/
, but I’m not confident that is what the next page link is pointing to. It might be missing the Benelux part.Regardless of what the next page link is, entering
your-domain.tld/benelux/sample/2/
in your browser will hopefully result in the next page of Benelux posts.I do not see any reason to check for the ‘s’ parameter on the sample page unless the same template is also used for the static front page of your site. (assuming the search form’s action is still pointing to your site’s home page)
If the front page is using the same template, you should get the region parameter from
$_REQUEST['region']
so that either GET or POST requests are covered. There’s a slight security issue with$_REQUEST
, but it shouldn’t be an issue in this context.Now the search form itself. Does this appear on the sample page? If so, instead of trying to get the region out of the query, see if you can use
$_GET['region']
(or$_REQUEST['region']
on a front page template). Using the query for region should have worked, but it’s more complicated. If$_GET['region']
works, it greatly simplifies things.On whatever page loads after the form submits is where using
$_POST
is appropriate, like what you currently have for the sample page. However, if the page can be requested with GET, you need to use$_REQUEST['region']
.$_POST['s']
is still OK because search requests will only come in via POST. Only the region parameter needs to work for both.We will still need to get the query var part working at some point for other templates that use the main query and do not use
get_posts()
, but let’s just focus on getting sample and the search form working first.See below information what i got at the moment. I activated the var_dump on the sample page only.
My home page is a custom template where you can select International or Benelux. Name custom template = startpagina.php and has a custom header-start.php and a custom footer-start.php.
For the main page of International en Benelux i got a custom news template based on the same name category. For Benelux i named the template file newslider-benelux.php and international newslider-international.php both have a custom header.php (header-slider.php and header-slider2.php)
Both pages get posts in the custom slider and posts items on the page with this code:
<?php $args = array( 'post_type' => 'post', 'category_name' => 'benelux', 'posts_per_page' => 6, 'paged' => $paged ); query_posts( $args ); ?>
For all pages benelux and international i got a custom template named benelux-page.php and international-page.php with a custom header (header-benelux.php and header international.php).
For all posts benelux and international i got a custom template named single-benelux.php and single-international.php with the same custom header (header-benelux.php and header international.php).
For the sample page i made a copy from the benelux page template and named it test-page.php. The sidebar should be the standaard benelux sidebar. And the text from this page should be normal (Lorum Ipsum). At the moment its loading the last post.
What i need is if someone uses the search function he/she should stay in the region – benelux. So the benelux template should be loaded with the benelux menu and show all the posts according to the search result with taxonomy location / benelux.
Thanks for the explanation, it really helps me get the overall picture. So the search form is on all pages, like in sidebar or header, yes? I seem to have lost the link to your site that you sent me, my apologies. I don’t really need it right now, but if you get a chance to email it to me again, it might come in handy. tia
I wasn’t thinking straight when I asked about your home page. I asked because that is where the search form submits to. I neglected to consider that WP probably redirects search posts to another template. Which one depends on the theme, but typically search.php. Additionally, the search results template does not actually execute the search, it just loops through the results. The search is handled internally, so we may need to manage the region term through ‘pre_get_posts’ and
$wp_query
.Because search is handled by WP internally, there is no point in checking for
$_POST['s']
on any template except the one that is loaded to show search results, and there only if the results come fromget_posts()
orquery_posts()
. It doesn’t hurt to check on other templates, but the ‘s’ query var should never occur there.The important thing to focus on right now is getting the sample page to only show Benelux posts when requesting /benelux/sample/. This should do that (using get instead of post):
<?php $args = array(); if ( array_key_exists('region', $_GET )) $args['category_name'] = $_GET['region']; $posts = get_posts( $args ); ?>
The other thing to get right is the region field on the search form. I’m hoping this would do it:
<?php echo "<input type='hidden' name='region' value='{$_GET['region']}' />"; ?>
If you do not get only Benelux posts using the above code, then there is a problem with the rewrite rules. If there’s a problem, it might be useful to
global $wp_rewrite; var_dump($wp_rewrite);
on the sample template.FYI, using
get_posts()
orquery_posts()
is not an efficient way to display main content. It’s OK for now, but you might want to make your templates more efficient in the future by using ‘pre_get_posts’ instead. Or not, it’s your decision.For now, I’d just like to know if using
$_GET['region']
works or not.First little info; i changed international to World Wide (slug: worldwide).
I have put the above code <input… to the searchform.php but this gave me a error “Notice: Undefined index: region” so i changed this back to:
<?php global $wp_query; $region = $wp_query->is_main_query()? $wp_query->get('region') :''; echo "<input type='hidden' name='region' value='$region' />"; ?>
And i did add the following code to the search.php
<?php $args = array(); if ( array_key_exists('s', $_POST )){ $args = array( 's' => $_POST['s'], );} if ( array_key_exists('region', $_POST )) $args['category_name'] = $_POST['region']; $posts = get_posts( $args ); ?>
I can now find the region with the var_dump. But im getting posts from benelux and World Wide(international). And it also changed the menu to the main menu.
Getting the region to show up in the query vars is a major accomplishment! Yes, there’s still more to work out, but if we could not get even the query var working, then the entire scheme would have been doomed. But it’s there, the scheme lives! On intensive care, but alive ??
On the sample and search page’s template you should be getting posts like this:
if ( array_key_exists('region', $_GET )) $args['category_name'] = $_GET['region']; $posts = get_posts( $args );
(GET, not POST. POST is used only when the form method is POST, last I recall your form method is GET)
What code is normally used to load the Benelux menu? And the World Wide menu?
Please confirm the hidden region field in the search form has the appropriate value when you view a page’s source HTML.
i have put the above code on the sample page. It now loads the last post and the sidebar from that post. Im getting the following error on this page: “Notice: Undefined variable: args”
I have put a search field on this sidebar so we can test. When i search im still getting post from benelux and world wide.
this is my current searchform:
<form role="search" method="get" class="form-search" action="<?php echo esc_url( home_url( '/' ) ); ?>"> <div class="input-group"> <label class="screen-reader-text" for="s"><?php _e( 'Search for:', 'sparkling' ); ?></label> <input type="text" class="form-control search-query" placeholder="<?php echo esc_attr_x( 'Search…', 'placeholder', 'sparkling' ); ?>" value="<?php echo get_search_query(); ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label', 'sparkling' ); ?>" /> <?php global $wp_query; $region = $wp_query->is_main_query()? $wp_query->get('region') :''; echo "<input type='hidden' name='region' value='$region' />"; ?> <span class="input-group-btn"> <button type="submit" class="btn btn-default" name="submit" id="searchsubmit" value="<?php echo esc_attr_x( 'Search', 'submit button', 'sparkling' ); ?>"><span class="glyphicon glyphicon-search"></span></button> </span> </div> </form>
The menu is loaded with “<?php sparkling_header_menu(); ?>”
// This theme uses wp_nav_menu() in one location.
register_nav_menus( array(
‘primary’ => esc_html__( ‘Primary Menu’, ‘sparkling’ ),
‘footer-links’ => esc_html__( ‘Footer Links’, ‘sparkling’ ) // secondary nav in footer
) );Im using the following plugins for the menu:
Custom Menu Wizard
Menu SwapperI cant find the hidden value on the page. When i example search for “Basel”.
You still need
$args = array();
on the sample page template, just not the ‘s’ related code. More disconcerting is the$_GET['region']
value is not defined ?? But yet'region' => 'benelux'
showed up when you hadvar_dump($wp_query)
?Did you search for the value of the hidden field named ‘region’ on the sample page or search results? I’m interested in what’s on the sample page for now. The sample page influences the search results, so if sample is not right, we cannot expect search results to be right. I found the hidden field myself on sample, the value is ”, which tells us
$wp_query
is no longer the main query when the sidebar is output. This can be dealt with once the proper rewrite rule is applied. The rewrite rule seems to be the main problem still.Another strange thing is /worldwide/sample brings up a ‘sample’ post with a different sidebar, it appears a completely different template is used, which indicates other rewrite rules are in place besides the one we want.
I’ll need to look into your plugins further to determine how the menu swapping is actually accomplished, but we need to resolve query vars and rewrite rules first. Please add the following to test-page.php, just above
wp_footer();
global $wp_rewrite, $wp_query; var_dump( $wp_rewrite ); var_dump( $wp_query->query_vars );
The ‘s’ related code is not presend on the sample page only this code:
<?php if ( array_key_exists('region', $_GET )) $args['category_name'] = $_GET['region']; $posts = get_posts( $args ); ?>
On the search result page the ‘region’ is displayed with the var_dump but not ‘benelux’.
I cant find the region nor benelux on the sample page.
For the moment is still got this code on the search result page:<?php $args = array(); if ( array_key_exists('s', $_POST )){ $args = array( 's' => $_POST['s'], );} if ( array_key_exists('region', $_POST )) $args['category_name'] = $_POST['region']; $posts = get_posts( $args ); ?>
Another strange thing is /worldwide/sample brings up a ‘sample’ post with a different sidebar, it appears a completely different template is used, which indicates other rewrite rules are in place besides the one we want.
I didnt know this was possible. But the text that is shown is the original text from the /benelux/sample page. It’s not a post. The sidebar is the default sidebar. If you look at the breadcrumbs you can still see the correct path. The next and previous buttons gone crazy as well. And should not be present on this page.
I have put the var_dump on the test tamplate above get_footer();
Hi Taro,
Apologies for the slow response, I was traveling and was unable to focus my attention on your site. Thanks for adding the var_dumps, from the output I’m fairly sure there’s a rewrite conflict so that the region query var never gets properly assigned.
I noticed your permalink structure is
/%category%/%postname%
, which of course makes sense, but this fact failed to register with me earlier. We can make use of this instead of creating a ‘region’ query var, which should eliminate the rewrite conflict.In order to avoid introducing other possible conflicts, we need to pretty much start over. Keep backups of what you have now, because some of the code can possibly be reused. In the working copies, remove all code that we’ve introduced.
The template for the sample page should basically be a secondary WP_Query loop that queries for all posts with the category name taken from
$wp_query->get('category_name')
. The sample page should have both benelux and worldwide categories assigned to it so it will work for both situations. The secondary query is where the posts are limited by category, even though the category is coming from the query for the page.The code in the example linked above only outputs titles. You will want to insert the previous template loop code in place of the example’s
echo '<li>' . get_the_title() . '</li>';
.In a similar vein, the search form’s hidden field should now be named ‘category_name’ and the value should also come from
$wp_query->get('category_name')
. Be sureglobal $wp_query;
appears on the sample template as well.This should get the page requested by
/benelux/sample/
showing the proper Benelux posts and the search form’s hidden field should be correct. The menu still won’t be right for now, I still need to study how the menu plugin works before that part will work correctly. The search results may not work correctly either. These will be addressed, but first let’s get the sample page content working correctly.Anticipating the need for some further debugging of the sample template, please include this line above the footer call:
var_dump( $wp_query->query_vars );
After you remove the rewrite rules we added, don’t forget to go to the permalink settings and re-save them (without actually changing any settings). This forces all the current rules to be re-generated.
backup code used at the moment:
function.php: <?php function custom_select_region() { add_rewrite_rule('^([^/]*)/([^/]*)/?','index.php?pagename=$matches[2]®ion=$matches[1]','top'); add_rewrite_rule('^([^/]*)/([^/]*)/([0-9]{1,})/?','index.php?pagename=$matches[2]®ion=$matches[1]&paged=$matches[3]','top'); } add_action('init', 'custom_select_region', 0 ); ?> <?php function custom_select_region_query_vars($query_vars) { $query_vars[] = 'region'; return $query_vars; } add_filter('query_vars', 'custom_select_region_query_vars'); ?> searchform.php: <?php global $wp_query; $region = $wp_query->is_main_query()? $wp_query->get('region') :''; echo "<input type='hidden' name='region' value='$region' />"; ?> test-page.php: <?php if ( array_key_exists('region', $_GET )) $args['category_name'] = $_GET['region']; $posts = get_posts( $args ); ?> [18-05-16 15:41:08] Taro van Gelderop: <?php global $wp_query; echo '<pre>'; if ( $wp_query->is_main_query()) var_dump( $wp_query ); echo '</pre>'; ?> And infront of footer include <?php global $wp_rewrite, $wp_query; var_dump( $wp_rewrite ); var_dump( $wp_query->query_vars ); ?>
I like to know if you whant me to change the sample page template to a post template?
Current code for the page template:
<?php while ( have_posts() ) : the_post(); ?> <?php get_template_part( 'content', 'page' ); ?> <?php // If comments are open or we have at least one comment, load up the comment template if ( get_theme_mod( 'sparkling_page_comments', 1 ) == 1 ) : if ( comments_open() || '0' != get_comments_number() ) : comments_template(); endif; endif; ?> <?php endwhile; // end of the loop. ?>
Current code for the post template:
<?php if ( have_posts() ) : ?> <?php /* Start the Loop */ ?> <?php while ( have_posts() ) : the_post(); ?> <?php /* Include the Post-Format-specific template for the content. * If you want to override this in a child theme, then include a file * called content-___.php (where ___ is the Post Format name) and that will be used instead. */ get_template_part( 'content', get_post_format() ); ?> <?php endwhile; ?> <?php sparkling_paging_nav(); ?> <?php else : ?> <?php get_template_part( 'content', 'none' ); ?> <?php endif; ?>
And you whant me to change ‘<?php while ( have_posts() ) : the_post(); ?>’ to the following?
<?php // The Query $the_query = new WP_Query( $args ); // The Loop if ( $the_query->have_posts() ) { echo '<ul>'; while ( $the_query->have_posts() ) { $the_query->the_post(); echo '<li>' . get_the_title() . '</li>'; } echo '</ul>'; } else { // no posts found } /* Restore original Post Data */ wp_reset_postdata(); ?>
Changed this on the searchform.php:
<?php
global $wp_query;
$region = $wp_query->is_main_query()? $wp_query->get(‘category_name’) :”;
echo “<input type=’hidden’ name=’region’ value=’$region’ />”;
?>
- The topic ‘Search result based on menu category’ is closed to new replies.