Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

This is a question based on the comments from the answer here.

I'm using the following code to create a couple of different search boxes for my website:

<form action="<?php echo home_url( '/glossary/' ); ?>" method="get">
    <p style="font-size:12px;">SEARCH<strong class="dkblue">GLOSSARY</strong></p>
    <input type="text" name="s" value="" />
    <input type="submit" value="GO" class="glossary_submit" />
</form>

<form id="profilesearch" action="<?php echo home_url( '/species/' ); ?>" method="get">
    <input type="text" size="50" class="default-value" value="SEARCH" name="s" />
    <input type="submit" value="GO" class="profilesearch_submit" />
    <!-- <p class="tinysearch"><a href="/dev/advanced-search/">ADVANCED SEARCH</a></p> -->
    <input type="checkbox" name="showthumbnails" id="showthumbnails" class="checkbox" <?php if ($_POST["showthumbnails"] == "on") { echo 'checked="checked" '; } ?>/><label for="showthumbnails">HIDE THUMBNAILS</label>
</form>

My glossary CPT has the following creation $args:

$args = array(
  'labels' => $labels,
  'public' => true,
  'publicly_queryable' => true,
  'exclude_from_search' => true,    
  'show_ui' => true,
  'show_in_menu' => true,
  'query_var' => true,
  'capability_type' => 'post',
  'has_archive' => false,
  'hierarchical' => true,
  'menu_position' => 40,
  'menu_icon' => $this->plugin_url . 'images/glossary.png',
  'supports' => array('title','editor','thumbnail','page-attributes')
);

And my species CPT has these:

$args = array(
  'labels' => $labels,
  'public' => true,
  'publicly_queryable' => true,
  'show_ui' => true,
  'show_in_menu' => true,
  'query_var' => true,
  'has_archive' => true,
  'capability_type' => 'post',
  'has_archive' => true,
  'hierarchical' => false,
  'menu_position' => 5,
  'menu_icon' => $this->plugin_url . 'images/fish20.png',
  'supports' => array('author','thumbnail','excerpt','comments','revisions')
);

Currently, when I submit a search from the glossary form, the URL changes to: /glossary/?s=term. When I submit a search from the species form, the URL changes to: /search/term.

The glossary URL does what it's meant to do - searches for glossary CPT types only. The species URL however simply searches for everything.

If I change has_archive to false, the searches work as per the above glossary. If I change it to true, the searches work as per the above species.

What I want both to do is this: change URL to /search/cpt-slug/term, i.e. /search/species/bettas and search for only posts with that CPT.

Have I done something wrong with my $args?

share|improve this question

3 Answers 3

up vote 2 down vote accepted
+50

Most unfortunate, while my original solution was elegant I did not foresee this complication, and I apologise for the inconvenience.

So, I provide an alternative solution.

Firstly to get your fancy search query:

Your markup will need to change, but this will intercept the URLs and rewrite them correctly internally, it is similar to the other answer but prettier, faster, easier to read, and in a single function

function custom_rewrite( $wp_rewrite ) {
    $feed_rules = array(
        'search/(.+)/(.+)'      =>  'index.php?post_type='.$wp_rewrite->preg_index(1).'&s=' . $wp_rewrite->preg_index(2)
    );
    $wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
}
// refresh/flush permalinks in the dashboard if this is changed in any way
add_filter( 'generate_rewrite_rules', 'custom_rewrite' );

Thus example.com/search/post/bannana will search all posts of type 'post' for bannana.

If you would prefer instead not to 'search' but to instead show a term, all you need to do is modify the query variables in the rewrite rule.

You can use the monkeyman rewrite rules analyser plugin to help you, by putting in URLs and being shown which rewrite rule handles it and the priority/order of said rules

BUT

However, you will not be able to use the elegant html markup to use these URLs, it will not play nicely, you will need to modify where the forms is submitted to which means while this might sound like a marvellous idea, in practice the implementation means you will need at least 1 redirect for a searchbox to work with these URLs, which is not ideal at all.

For your species search problem

Also modify your species registration to be more specific/accurate:

$args = array(
  'labels' => $labels,
  'public' => true,
  'publicly_queryable' => true,
  'exclude_from_search' => false, // lets not guess what this will be, lets be authorative
  'show_ui' => true,
  'show_in_menu' => true,
  'query_var' => true,
  'has_archive' => true,
  'capability_type' => 'post',
  'has_archive' => true,
  'hierarchical' => false,
  'menu_position' => 5,
  'menu_icon' => $this->plugin_url . 'images/fish20.png',
  'supports' => array('author','thumbnail','excerpt','comments','revisions')
);

But, while this might fix it, I suspect not. Rereading your question, I see it rewrites to /search/term, but WordPress does not do this by default. I suspect you have code somewhere else that rewrites search terms into a prettier version for general post searches, but this is interfering, be it because of the order of where its added in the code or something else.

Since I can't see your entire codebase, and I'm not sure what this search code prettification looks like, I can't help you any further than to point you in its directions ( and to conditionally rewrite if post_type is not set rather than always).

edit: give this a try:

function custom_rewrite( $wp_rewrite ) {
    $feed_rules = array(
        'species/(.+?)(/[0-9]+)?/?$'      =>  'index.php?post_type=species&species='.$wp_rewrite->preg_index(1).'&page='.$wp_rewrite->preg_index(2)
    );
    $wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
}
// refresh/flush permalinks in the dashboard if this is changed in any way
add_filter( 'generate_rewrite_rules', 'custom_rewrite' );
share|improve this answer
    
Cheers Tom, I'll have a go at this tonight :) –  dunc Mar 20 '12 at 16:13
    
Thanks for this Tom. Your rewrite rule is working, but the searches still aren't. My species search ends up with this URL: /search/species/?s=test and my glossary /glossary/?s=test. Any ideas? I haven't changed the markup, still using this format: <form id="profilesearch" action="<?php echo home_url( '/species/' ); ?>" method="get">. –  dunc Mar 24 '12 at 13:13
    
But if you go directly to the expected URL it works no? hmmm in that case you need to make sure it goes to the correct location but I'm not sure how you would account for that, which means that rewrite rules on their own aren't enough. –  Tom J Nowell Mar 24 '12 at 21:40
    
Can you install the monkeyman rewrite analyser plugin and put in the expected URL and see what rules are activated? –  Tom J Nowell Mar 24 '12 at 21:41
    
Also, add exclude_from_search => false, as it may be autogenerating the value based on has_archive and public –  Tom J Nowell Mar 24 '12 at 21:43

You'll have to work on permalinks. I don't have time at the moment but you can find some info here: http://shibashake.com/wordpress-theme/wordpress-permalink-add

Here's some code to get you started, it's based on another article that was taken down, I can't guarantee it will work.

add_filter('wp_loaded','bfr_add_permastruct');
add_filter('rewrite_rules_array','bfr_add_permalink_rule');

function bfr_add_permastruct(){
    add_permastruct('ctp_search', 'search/%post-type%/%postname%');

  //Remember to flush_rules() when for the first time 
  //$wp_rewrite->flush_rules();
}

// Adding a new rule
function bfr_add_permalink_rule($rules)
{
    $newrules = array();
    $newrules['search/([^/]+)/([^/]+)?$'] = 'index.php?post_type=$matches[1]name=$matches[2]';
    return $newrules + $rules;
}
share|improve this answer
    
Nice, though the issue here si that it will add the rule everytime wordpress runs, not just when the rewrite rules are generated –  Tom J Nowell Mar 20 '12 at 18:56

Thanks to Tom, I've worked out what my problem was...!

I found this little nugget in my functions.php. Must've been from literally a year ago as I don't even remember putting it in!

add_action( 'template_redirect', 'my_rewrite' );
function my_rewrite() {

    if ( is_search() and false === strpos( $_SERVER['REQUEST_URI'], '/search/' ) ) {
        wp_redirect( get_bloginfo( 'home' ) . '/search/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 's' ) ) ) );
        exit();
    }

}

This was causing my /species/search/ to fail. Replacing it with this has done the trick:

add_action( 'template_redirect', 'my_rewrite' );
function my_rewrite() {

    if ( is_search() and false === strpos( $_SERVER['REQUEST_URI'], '/search/' ) ) {
        if ( strpos( $_SERVER['REQUEST_URI'], '/species/' ) )
            wp_redirect( get_bloginfo( 'home' ) . '/species/search/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 's' ) ) ) );
        else if ( strpos( $_SERVER['REQUEST_URI'], '/glossary' ) )
            wp_redirect( get_bloginfo( 'home' ) . '/glossary/search/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 's' ) ) ) );
        else
            wp_redirect( get_bloginfo( 'home' ) . '/search/' . str_replace( ' ', '+', str_replace( '%20', '+', get_query_var( 's' ) ) ) );

        exit();
    }

}

Next up, I had to change has_archive to true on my glossary CPT.

Finally, I used Tom's rewrite rules and some knowledge from this excellent post to get my pretty URLs working:

/* --- rewrite rules for searches...*/
function custom_rewrite( $wp_rewrite ) {
    $species = array(
        '(species|glossary)/search/(.+?)(/page/([0-9]+))?/?$'      =>  'index.php?post_type='.$wp_rewrite->preg_index(1).'&s='.$wp_rewrite->preg_index(2).'&paged='.$wp_rewrite->preg_index(4)
    );  

    $wp_rewrite->rules = $species + $wp_rewrite->rules;
}
// refresh/flush permalinks in the dashboard if this is changed in any way
add_filter( 'generate_rewrite_rules', 'custom_rewrite' );

I now have working pretty URLs on my custom post type searches, AND pagination: /species/search/term, /species/search/term/page/2/ and /glossary/search/term, etc. all work correctly.

Thanks Tom, credit goes to you!

share|improve this answer
1  
yay! ^_^ Glad you got everything working, and you improved on my code too! –  Tom J Nowell Mar 31 '12 at 20:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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