4

I am using WordPress 3.3.1 and new to this system. I want to redirect the search query to the post if query exactly matches post title of some post. I also want it to run before any search query function and hooks or filter. I have made some changes in query.php in include folder

$search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}'))";

and wrote some plugin function like this:

add_action('template_redirect', 'single_result');
function single_result() {
    if (is_search()) {
        global $wp_query;
        if ($wp_query->post_count == 1) {
            wp_redirect( get_permalink( $wp_query->posts['0']->ID ) );
        }
    }
}

I have also some function that need to run just after this search query and has "get_header" hooks. So far the search query match and redirect is not matching and returning as aspected. It most of the time slips out and don't redirect perfectly. I want search and redirect to be very perfect. Any help will be highly appreciated and thankful. Thank you.

2
  • I would create a custom search page, instead of using the Wordpress search form. Make this page have a search box, and give it a unique page template. In the page template, provide the PHP code when the form is submitted to itself, to take the search query and see if you can get a post ID from the query (check to see if the search is an exact post name). If you can, do a PHP redirect before any information is sent to the browser (before any other Wordpress includes, functions, or HTML). If you can't get a post ID, then go ahead and redirect the search query to the actual Wordpress search form.
    – miahelf
    Commented Apr 17, 2012 at 6:36
  • 2
    Also editing the core Wordpress files such as query.php is not suggested because your changes will be overwritten if you ever update Wordpress.
    – miahelf
    Commented Apr 17, 2012 at 6:37

1 Answer 1

2

First, don't hack core files (unless you intend to submit a patch :) ).

Second, what you are doing isn't really checking to see if the title exactly matches the search string. What you are doing it checking to see if there is only one result. That doesn't mean the title matches. Undo the core hack, then do this:

function redir_title_match($a) {
  if (is_search()) {
    global $wp_query;
    $s_str = $wp_query->query_vars['s'];
    foreach ($wp_query->posts as $p) {
      if ($p->post_title == $s_str) {
        wp_safe_redirect(get_permalink($p->ID));
        exit();
      }
    }
  }
}
add_filter('template_redirect','redir_title_match');

That is case sensitive. If you don't want that use strtolower by making this change to line 6:

if ($p->post_title == $s_str) {
=>
if (strtolower($p->post_title) == strtolower($s_str)) {

Also, this query runs after the WordPress search, which does not match what the OP requested. However, it is necessary to run a query so it makes sense to use the default query.

@Rarst notes below in the comments that this is not a completely reliable solution. I believe that to be true though I don't know how much it would matter in practice. Here, however, is an option that should be reliable but adds a query to the search page.

function redir_rigid_title_match() {
  if (is_search()) {
    global $wp_query,$wpdb;
    $s_str = $wp_query->query_vars['s'];
    $m = $wpdb->get_var($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_title = %s",$s_str));
    if (!empty($m)) {
      wp_safe_redirect(get_permalink($m));
      exit();
    }
  }
}
add_filter('pre_get_posts','redir_rigid_title_match');

As above, this is case sensitive.


3
  • Hmm... I see the idea behind looking for a match in posts set, but note that post with matching title can be on different page of results (since native WP search doesn't do any kind of relevance sorting) and not included in it. It is not guaranteed that it will be single search result at all, that assumption is not valid.
    – Rarst
    Commented Nov 18, 2012 at 18:27
  • @Rarst, do you mean that I can't count on the matching post being in the first page of the results? That is probably true, technically, but in testing every time I have put in an exact post title it shows up very near the top and often as the first return. So, I believe you are correct, but I don't see it making much difference in practice. The only other option would be to run a second query and I try to avoid that. I can add that option to the answer though.
    – s_ha_dum
    Commented Nov 18, 2012 at 19:10
  • Yep. It's overly broad assumption. It very well might be true for content you are typically working with, but same can't be said for any content possible out there.
    – Rarst
    Commented Nov 18, 2012 at 19:59

Your Answer

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

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