• Hello!

    I’d like to change the default WordPress search URL. I was searching for a solution, found the code below on almost every site I visited:

    /**
    * Change search page slug.
    */
     
    function wpb_change_search_url() {
        if ( is_search() && ! empty( $_GET['s'] ) ) {
            wp_redirect( home_url( "/search/" ) . urlencode( get_query_var( 's' ) ) );
            exit();
        }   
    }
    add_action( 'template_redirect', 'wpb_change_search_url' );

    The code by itself works I guess, but the search now looks completely different than before, the whole search page is changed – instead of products being positioned normally, they are positioned below eachother. You can see this here.

    Let’s say for example that I’m searching for “Bazen”. The default search looks like /?s=bazen&post_type=product. What I’d like is just a simple /iskanje/bazen

    If I change /search/ in the code that I added to this request, I get the proper URL, but the page just shows 404 error.

    How can I edit this?

    Kind regards

    • This topic was modified 2 years, 7 months ago by jazzu.

    The page I need help with: [log in to see the link]

Viewing 15 replies - 1 through 15 (of 17 total)
  • If I change /search/ in the code that I added to this request, I get the proper URL, but the page just shows 404 error.

    See if this comment and code snippet by Allewar on the WPBeginner.com’s post you quoted works for you.

    https://www.wpbeginner.com/wp-tutorials/how-to-change-the-default-search-url-slug-in-wordpress/#comment-1103269

    Thread Starter jazzu

    (@jazzu)

    Hi @gappiah !

    Thank you for your reply. I tried it, now my code looks like this:

    /**
    * Change search page slug.
    */
     
    function wpb_change_search_url() {
        if ( is_search() && ! empty( $_GET['s'] ) ) {
            wp_redirect( home_url( "/search/" ) . urlencode( get_query_var( 's' ) ) );
            exit();
        }   
    }
    add_action( 'template_redirect', 'wpb_change_search_url' );
    
    function re_rewrite_rules() {
    global $wp_rewrite;
    $wp_rewrite->search_base = ‘iskanje’;
    $wp_rewrite->pagination_base = ‘stran’;
    $wp_rewrite->flush_rules();
    }
    add_action(‘init’, ‘re_rewrite_rules’);

    However, the Allewar’s part that I added doesn’t do anything for me. It still just changes the URL to /search/. It still changes the layout of the products, which I don’t want. If you want to check, here’s the /search/%C4%8Drpalka link.

    Kind regards

    Moderator bcworkz

    (@bcworkz)

    search/bazen/?post_type=product yields the correct layout. Without the post type query string WP uses its normal blog search results template instead of the products template. You could possibly use the “search_template” filter to force WP to use the products template for any search. If you still need blog search functionality, you could distinguish product search from blog search through the global $wp_query object.

    Thread Starter jazzu

    (@jazzu)

    Hi @bcworkz !

    Thank you for your reply. I understand what you mean. No, I don’t need or want blog search functionality, I need the search to only find products, but sadly, I don’t know what to change or add in the code to do that. Is it the get_query_var (‘s’) part in the third line?

    Kind regards

    Moderator bcworkz

    (@bcworkz)

    If you don’t mind the post type query string in the URL, you’re correct, concatenating '/?post_type=product' after the urlencode get_query_var bit would be the simplest solution.
    wp_redirect( home_url( "/search/" ) . urlencode( get_query_var( 's' ) ) . '/?post_type=product' );

    The “search_template” filter approach is the better solution IMO (no query string needed), but requires reasonable PHP coding skillz.

    Thread Starter jazzu

    (@jazzu)

    Hi @bcworkz !

    No, I don’t want the actual URL to display the post type, I just want it to search for the products. Yeah, I have practically no PHP coding skills, so there’s that.

    Kind regards and thank you

    Moderator bcworkz

    (@bcworkz)

    Another possibility would be to alter the ‘/search/’ rewrite rule to include the product type URL query string. The additional code jazzu suggested is a start, but there’s another $wp_rewrite element to alter. I’m unsure which it’d be, but it’s in there somewhere.

    Thread Starter jazzu

    (@jazzu)

    I changed the code to:

    /*		Change search page slug.		*/
     
    function wpb_change_search_url() {
        if ( is_search() && ! empty( $_GET['s'] ) ) {
            wp_redirect( home_url( "/search/" ) . urlencode( get_query_var( 's' ) ) . '/?post_type=product' );
            exit();
        }   
    }
    add_action( 'template_redirect', 'wpb_change_search_url' );

    Now the URL looks a bit better, but I still can’t manage to translate the /search/ to /iskanje/ and I would still need to remove the post_type=product from the URL.

    Moderator bcworkz

    (@bcworkz)

    You could try using add_rewrite_rule(). There are some examples from users at the bottom of the page you can use for guidance. The challenge would be coming up with a regexp that matches /search/ or /skanje/ requests without matching others. Also, the index.php parameter will need all query vars in its query string to accomplish the correct search query. The index.php request will not be seen by end users.

    If you can get this working correctly, you may not need any other code discussed here so far. You will need to flush rewrite rules any time you add or change the above linked function. jazzu shows us one way to do so, but it only needs to be done once. It’s wasteful to do it on every “init” action. You can flush the rules by simply visiting the permalinks settings screen, no coding required.

    If you need help composing a good regexp, try regexr.com. It’s sort of like jsfiddle for regexp.

    Thread Starter jazzu

    (@jazzu)

    Right. I checked the add_rewrite_rule() link you added and regexr.com. Like I said, sadly I don’t have any experience with PHP coding yet, so I don’t know what I’m searching for exactly. I was checking out plugins, but couldn’t find any that would allow me to do this. When you said that the challenge would be coming up with a regexp that matches /search/ requests without matching others, what did you mean by that?

    Moderator bcworkz

    (@bcworkz)

    If you were to dump out the global $wp_rewrite that’s used in add_rewrite_rule() source code, you’d see an array list of various rewrite rules which include regexp expressions. When WP receives a request, it goes down the list, seeing if each regexp will match the request. If there is not a single match within the entire list, WP will return a 404 response. More than likely, it’ll match something in the list. For the first match found, WP will execute the related file, usually its main index.php in the root installation folder followed by a bunch of query vars, for exampleindex.php?page_id=12&food=$matches[2]&style=$matches[1].

    The $matches values are those captured from the regexp, the portions matched within regexp () chars. In the regexr tool, if you hover over matched values in the text example you can provide, a tool tip will show you what portion of the match was captured. Thus you can extract out certain values from the matched request and use them as query var values.

    WP will go with whatever regexp if first finds as a match. If your search regexp were to match a non-search request meant to get some other resource, WP would treat it as a search request none the less. This is why it’s important to only match search requests and nothing else. When all search requests start with /search/ this should be pretty easy. It gets a lot more difficult if there is no “base” element like /search/ or /category/ or /tag/, etc.

    Modifying one of the examples from the code reference doc I linked earlier, I think you want something like this:

    function custom_rewrite_rule() {
        add_rewrite_rule('^search/([^/]*)/?','index.php?post_type=product&s=$matches[1]','top');
    }
    add_action('init', 'custom_rewrite_rule', 10, 0 );

    After adding this code, don’t forget to flush rules by visiting the permalinks settings screen.

    If regexps are alien to you, it’d be informative to try out the regexp from the above code at regexr.com. Replace the test text with some typical site URLs and place the regexp between the gray expression slashes. The gray slashes are regexp delimiters, sort of like quotes. WP adds something similar in for us. Do not include the initial ^ as that’s a server thing and not really part of proper regexp. The second ^ is proper regexp usage. The first ^ means the match must start immediately after the domain name and first / of an URL. One more adjustment to use the tool, all literal / have to be escaped because they are also used as delimiters. Add a backslash in front of each. So you’d actually paste search\/([^/]*)\/? into the tool. Hovering over parts of the expression and the match in the regexr tool will yield useful information in the tool tips.

    Thread Starter jazzu

    (@jazzu)

    Hello @bcworkz !

    Thank you for your reply. I removed my code and added

    function custom_rewrite_rule() {
        add_rewrite_rule('^search/([^/]*)/?','index.php?post_type=product&s=$matches[1]','top');
    }
    add_action('init', 'custom_rewrite_rule', 10, 0 );

    After I added the code and flushed the permalinks, everything looked like it was originally. I also tried the same code in regexr.com, except that I changed it a bit, just like you said. I changed it to:

    function custom_rewrite_rule() { add_rewrite_rule('search\/([^/]*)\/?','index.php?post_type=product&s=$matches[1]','top');}add_action('init', 'custom_rewrite_rule', 10, 0 )

    Everything is green/yellow in the explain tab in tools. What do I do now?

    Moderator bcworkz

    (@bcworkz)

    Sorry for confusion in regexp syntax between WP rewrite rules vs. regexr. They are not identical and it cannot be helped. There are some quirks in using the tool that I was hoping to not need to explain. I thought it was was easier to simply drop the ^. You really do need it in the WP version, otherwise it’ll match “search” anywhere in any permalink. You only want it to match as a “base” argument which occurs immediately after the domain name in an URL.

    You don’t really need to escape / in WP because it uses a different delimiter. Regexr forces us to use / delimiters (the gray ones), so we’re forced to escape any / chars with a \. It’s actually OK to escape within WP as well, but the end result is even more confusing than it already is.

    The colors in the explain tab simply match the same colored chars in the regexp expression. They are simply to help you stay oriented. The screen I got is like this. Group #1 becomes $matches[1] in WP rewrite rules.

    I added this code to my test site:

    //enable /search/ path for products
    function custom_rewrite_rule() {
        add_rewrite_rule('^search\/([^/]*)\/?','index.php?post_type=product&s=$matches[1]','top');
    }
    add_action('init', 'custom_rewrite_rule', 10, 0 );

    I had previously installed WooCommerce on it and created a few example products. It’s a localhost site I call “lenny”. The product descriptions all have the same product descriptions: “Long description”. I requested https://lenny/search/description/.

    The expected shop search results page with the expected products is returned. Searching by product name results in that product being returned. Partial search terms return all products that match. Everything works as expected.

    I’m not sure why your results would be any different. Could it be browser caching? Try flushing your browser’s cache, then try another search.

    Thread Starter jazzu

    (@jazzu)

    Hello again.

    I don’t know why my results would be different. I tried clearing cache, I replaced this code

    /*		Change search page slug.		*/
    
    function wpb_change_search_url() {
        if ( is_search() && ! empty( $_GET['s'] ) ) {
            wp_redirect( home_url( "/search/" ) . urlencode( get_query_var( 's' ) ) . '/?post_type=product' );
            exit();
        }   
    }
    add_action( 'template_redirect', 'wpb_change_search_url' );

    With

    //enable /search/ path for products
    function custom_rewrite_rule() {
        add_rewrite_rule('^search\/([^/]*)\/?','index.php?post_type=product&s=$matches[1]','top');
    }
    add_action('init', 'custom_rewrite_rule', 10, 0 );

    and it returned back to default ?s=[searchterm]&post_type=product. I tried adding your code under the code I had before after that, like this

    /*		Change search page slug.		*/
    
    function wpb_change_search_url() {
        if ( is_search() && ! empty( $_GET['s'] ) ) {
            wp_redirect( home_url( "/search/" ) . urlencode( get_query_var( 's' ) ) . '/?post_type=product' );
            exit();
        }   
    }
    add_action( 'template_redirect', 'wpb_change_search_url' );
    
    //enable /search/ path for products
    function custom_rewrite_rule() {
        add_rewrite_rule('^search\/([^/]*)\/?','index.php?post_type=product&s=$matches[1]','top');
    }
    add_action('init', 'custom_rewrite_rule', 10, 0 );

    It just displayed the normal /search/[searchterm]/?post_type=product, and nothing changes. The code works to the part that it atleast shows the /search/[searchterm]/?post_type=product instead of /?s=, but ideally in my case would be /iskanje/[searchterm]

    I really didn’t expect changing the URL would be such a difficult issue ??

    • This reply was modified 2 years, 7 months ago by jazzu.
    Moderator bcworkz

    (@bcworkz)

    I really didn’t expect changing the URL would be such a difficult issue.

    It normally isn’t. add_rewrite_rule() in theory is pretty simple. Every site has its quirks though. Could be another plugin is interfering. Other than WC and a payment gateway, plus my test rewrite code, I don’t have any active plugins.

    You did remember to visit the permalinks settings screen after altering any related code, right? And somehow removed or disabled other related code? Using template_redirect is what was causing the wrong template to be used. The rewrite rule code alone should suffice. WC should see it’s a product search and cause the right template be used.

    Be sure there is no flush_rewrite_rules(); code in normal execution. Doing so at the wrong time can undo the added rewrite rule. If you’re still getting a visible redirect from /search/[searchterm] to /search/[searchterm]/?post_type=product, there might be an issue with what is considered the canonical URL. If that’s the case, canonical redirects can be managed through the “redirect_canonical” filter. But there shouldn’t be a canonical URL for search results pages.

    As a test, disabling all plugins but WC, a payment gateway, and the rewrite rule code; and using twenty twenty-one theme, would mean we both have virtually identical sites code-wise and we should expect virtually identical results. If the search URL works in that state, start restoring your site back to normal, one module at a time. Test the search URL after each. When the search request is redirected back to /search/[searchterm]/?post_type=product again, the last activated module is somehow interfering.

Viewing 15 replies - 1 through 15 (of 17 total)
  • The topic ‘Changing search URL’ is closed to new replies.