1

I have wordpress and woocommerce installed and I noticed that woocommerce's product search seems to use wordpress's search. Well, I don't like the search, and I'd rather alter it at the core rather than adding on extra pages and whatnot. Where is the core code at?

I've read that the core code does a LIKE %query% on post_content AND post-title, and I want to modify it so that it only searches the title. I want to know where the /core/ code is just in case I want to add extra functionality in the future (Probably will), I don't want to simply add a title filter ontop of the search results which would be the easiest solution, but I'm not looking for easy, I'm looking for complete control of my website.

However, doing a GREP search for "SELECT * from wp_posts" turns up nothing useful except from my W3 Super Cache plugin. Where is this search algorithm code at? Surely it's not some mystical, unmodifiable executable that's been binary encoded.

1

2 Answers 2

1

Quick tip - never, ever edit WP core files. Updates are released several times a year and you'll lose your changes, among other reasons (such as security).

Your theme and the particular template file in question is what determines how WP search is processed. Assuming no search plugin is active, and your theme is calling get_search_form(), you can follow the logic path laid out in the WordPress Codex page for that function: https://codex.wordpress.org/Function_Reference/get_search_form

WordPress will look for a searchform.php file in the active theme. If it finds one, it loads it. If not, it falls back to the core search form. Therefore, the proper way to modify the WP core search form is to ensure your theme (or child theme) has a searchform.php file available.

In that, you can create a custom query to search only the values you wish to return results for.

3
  • I think I'm going to just going to add core edits to a master list of edits, just in case I ever upgrade. Nov 12, 2015 at 2:31
  • 2
    Ever hear of Will Rogers? “There are three kinds of men. The ones that learn by reading. The few who learn by observation. The rest of them have to pee on the electric fence for themselves.” Good luck with those core edits.
    – jdm2112
    Nov 12, 2015 at 2:46
  • I peed at the fence and missed, and felt extremely relieved at the end. Eh, it was worth the venture I gander. Nothing ventured nothing gained, so say the wise men of the east. Nov 12, 2015 at 10:18
-4

Found it! The core search is found in wp-includes/query.php and the exact mysql code on my version is constructed on line 2094 under the function "parse_search( &$q )" and the line in question is this one:

$search .= $wpdb->prepare( "{$searchand}(($wpdb->posts.post_title LIKE %s) OR ($wpdb->posts.post_content LIKE %s))", $like, $like );

However, I do have a theme which has a searchform.php file. However, I wasn't able to find the MYSQL statements in there and I read on someone else's Q&A that modifying that file DID NOT modify the core search function (The one I pasted above) which was executed first, and then searchform.php was executed after the core search function was executed. So, to truly modify the search algorithm, it appears I need to change the core search function and I need to modify the line above to do so. Am I wrong? First time wordpress user here.

The reason why the core search sucks, is because short search queries like "cat" are useless, because nearly every post has 'cat' somewhere in it's post_content embedded in some word (Common words like... scat, deprecate,masticate,category,etc.), somewhere. [Btw, an actual user had to wade through 5 pages of search results, because nearly the whole store was in the search. Don't want to subject my users to that.]

So, I'd rather do something like...

post_title LIKE %qry% OR post_content LIKE % qry %; that is, do partial matches in the title and exact matches in the post_content.

Or better yet, post_title LIKE '% qry% OR 'qry%' OR post_content LIKE '% qry %'. (Gets the beginning of words in the title, the very beginning of the title, and exact matches in the content.)

Now I have to find this prepare() function, to figure out how to implement it. It doesn't appear that I can easily add that directly to the code, as it appears the percentage signs are added in the prepare function (Undesireable behavior; I need to add the percentage signs manually.).

[Edit, they're actually added earlier in the parse_search function]

Well, after investigating the code a bit more, I think I'd probably want to add a filter, lol (The core function is designed to do an exact search over all terms, or partial search on all terms, no real in-between.). "How to?" is the question I'm going to be racking my brain over the next few days, I can tell. a

(Edit, dag nabbit. I got it to work once, then I changed something, and could never get it to work again. I swear Wordpress likes to play tricks on me.)

EDIT: I tried adding the filter, it worked once, never worked again. So, I said screw it and edited the core file. Worked like a charm, no fuss, worked right away. But, you know, I'm not the risk-taking type so I did keep a backup of the original file just in case.

Here's my final code and, yes, it actually produces /awesome/ search results like I thought it would. The only words that don't work like they would, ideally, are homonyms. (i.e., words like 'can' which returns the entire store. But, I think that's an acceptable trade off. Think I should just disable content search with the way my store is currently setup.)

    protected function parse_search( &$q ) {
        global $wpdb;

        $search = '';

        // added slashes screw with quote grouping when done early, so done later
        $q['s'] = stripslashes( $q['s'] );
        if ( empty( $_GET['s'] ) && $this->is_main_query() )
            $q['s'] = urldecode( $q['s'] );
        // there are no line breaks in <input /> fields
        $q['s'] = str_replace( array( "\r", "\n" ), '', $q['s'] );
        $q['search_terms_count'] = 1;
        if ( ! empty( $q['sentence'] ) ) {
            $q['search_terms'] = array( $q['s'] );
        } else {
            if ( preg_match_all( '/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $q['s'], $matches ) ) {
                $q['search_terms_count'] = count( $matches[0] );
                $q['search_terms'] = $this->parse_search_terms( $matches[0] );
                // if the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence
                if ( empty( $q['search_terms'] ) || count( $q['search_terms'] ) > 9 )
                    $q['search_terms'] = array( $q['s'] );
            } else {
                $q['search_terms'] = array( $q['s'] );
            }
        }

        $n = ! empty( $q['exact'] ) ? '' : '%';
        $searchand = '';
        $q['search_orderby_title'] = array();
        foreach ( $q['search_terms'] as $term ) {
            if ( $n ) {
                $like = '%' . $wpdb->esc_like( $term ) . '%';
                $q['search_orderby_title'][] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $like );
            }

            $like1 = $n .' '. $wpdb->esc_like( $term ) . $n;
            $like2 = $wpdb->esc_like( $term ) . $n;
            $like3 = $n.' '.$wpdb->esc_like( $term ).' '.$n;
            $search .= $wpdb->prepare( "{$searchand}(($wpdb->posts.post_title LIKE %s) OR ($wpdb->posts.post_title LIKE %s) OR ($wpdb->posts.post_content LIKE %s))", $like1, $like2,$like3 );
            $searchand = ' AND ';
        }

        if ( ! empty( $search ) ) {
            $search = " AND ({$search}) ";
            if ( ! is_user_logged_in() )
                $search .= " AND ($wpdb->posts.post_password = '') ";
        }

        return $search;
    }

Now I'm starting to think that YITH ajax search plugin might start to be useful... (Just tested it, oh yeah, totally is!)

7
  • 1
    peeing is fun but you usually don't do it in public while other people are looking. You might have your own very good reasons for doing it but other observes might get the impression that it is not the horrible idea it is. Nov 12, 2015 at 10:26
  • I hardly care about what people think is "acceptable". I balance the risks and rewards and, in this case, functionality and make a decision. The risks in this case are very small and I have public record should I ever need reminding myself the changes I made, and I have a backup should I ever need the original. The risks? Pwah, what risks? There's nothing to that code that could be SQL injected that wasn't already SQL injectable. Nov 12, 2015 at 10:31
  • Core edits are a horrible idea and I've made that mistake. There will be pain with maintainability, and it looks like a filter on posts_search could probably do this. Honestly, the WP_Query class has so many hooks in it that that is about the last place you ever need to hack Core.
    – s_ha_dum
    Nov 12, 2015 at 13:57
  • it would cost you a one time effort of two hours to figure out the right answer and one hour every four months when you upgrade for eternity, in your way but if you like to suffer by all means go ahead.. Nov 12, 2015 at 15:30
  • I tried implementing a search filter and it worked once. Well, now that I think about it, I was doing a filter on 'parse_search', maybe I should go through the trouble of figuring out how to implement posts_search. Last time I tried, it kept complaining of a missing reference object to the word 'this', which broke the whole site. That got old, fast. My customers want a working site, not a broken one. And, I'm going to design my site so that it works the way my customers want it to work, not the way a bunch of pedantic purist wordpress geeks want it to. I never update anyway, it breaks things. Nov 12, 2015 at 18:57

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.