Redirect from URL with parameters to SEO friendly URL in .htaccess

479

tl;dr

# Redirect /Category.php?Category_Id=10&Category_Title=some-text
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^Category_Id=(\d+)&Category_Title=([\w-]+)$
RewriteRule ^Category\.php$ /Category/%1/%2? [R=301,L]

i changed generated link from bad seo structure to seo friendly structure and it works

Fair enough, glad you got it sorted, I assume you are using some kind of CMS? (This probably added something to your .htaccess I would think?)

Anyway, to address your initial question(s)...

Me: have you already changed the URL in your application to the "pretty" format? eg. The URL the user sees on the page is example.com/Category/10/some-text, not example.com/Category.php?Category_Id=10&Category_Title=some-‌text?

You: yes .but it's a lot.a have to make all url's pretty in all page and i'am doing this now.but i want to know if there is a htaccess solution i do it.so you say changing url in all pages is the only solution...

Whilst it's technically possible to implement this solely in .htaccess, without actually changing the URLs in your application, it's not recommended. It would deliver a bad user experience and would potentially be damaging to your site's SEO.

If you didn't change the URL in your application then every time a user clicked an internal link they would experience an external redirect (a second request) to the canonical URL (until the redirect was cached). That's an extra (unnecessary) request on your server. The old URL would be exposed to the user and copyable (eg. "Copy link address").

Ordinarily, the only reason to implement such a redirect is if the old URLs had already been linked to and/or search engines had already indexed the old URL structure. The redirect is then required in order to preserve SEO.

Internal rewrite (new "pretty" URL to old "ugly" URL)

In order to implement a user-friendly URL structure like this, you would need an internal rewrite that silently rewrites the request from the new "pretty" URL back to the old "ugly" (real) URL. The user only sees the new "pretty" URL. It is assumed from your question that you already had something like this (maybe not)? For example:

# Rewrite /Category/10/some-text
RewriteRule ^Category/(\d+)/([\w-]+)$ Category.php?Category_Id=$1&Category_Title=$2 [L]

$1 and $2 are backreferences to the captured groups in the RewriteRule pattern. ie. \d+ and [\w-]+ respectively.

If this was a new site then you could stop there, however...

External redirect (old "ugly" URL to new "pretty" URL) - optional

This redirect should go before the above rewrite in your .htaccess file:

# Redirect /Category.php?Category_Id=10&Category_Title=some-text
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^Category_Id=(\d+)&Category_Title=([\w-]+)$
RewriteRule ^Category\.php$ /Category/%1/%2? [R=301,L]

In order to check the query string part of the URL you must use a RewriteCond directive and check against the QUERY_STRING server variable (the RewriteRule pattern only matches against the URL-path part of the URL).

%1 and %2 are backreferences to the captured groups in the last matched CondPattern. ie. \d+ and [\w-]+ respectively. This is the reverse of the earlier rewrite.

The ? on the end of the RewriteRule substitution is required to remove the query string from the request. (Alternatively you can use the QSD flag on Apache 2.4+)

UPDATE: The condition that checks against the REDIRECT_STATUS environment variable ensures that we only redirect the initial request and not the rewritten request by the later directive (see above). The REDIRECT_STATUS env var does not exist (ie. is empty) on the initial request and is only set after the first internal rewrite/subrequest. (In a per-directory context (like .htaccess), the rewriting process essentially starts over after the last RewriteRule, and continues to do so until the URL passes through unchanged. The L flag simply causes the "current pass" through the rewriting process to end, triggering the process to effectively start again, using the now rewritten URL as input.)

Summary

Bringing this together, we have:

Options -Multiviews
RewriteEngine On

# Canonical www to non-www redirect
RewriteCond %{HTTP_HOST} !^example\.com
RewriteRule (.*) http://exmaple.com/$1 [R=301,L]

# Redirect /Category.php?Category_Id=10&Category_Title=some-text
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^Category_Id=(\d+)&Category_Title=([\w-]+)$
RewriteRule ^Category\.php$ /Category/%1/%2? [R=301,L]

# Rewrite /Category/10/some-text
RewriteRule ^Category/(\d+)/([\w-]+)$ Category.php?Category_Id=$1&Category_Title=$2 [L]

MultiViews will need to be disabled (if it's not already) for this particular example to work.

Share:
479

Related videos on Youtube

TheBlackBenzKid
Author by

TheBlackBenzKid

Updated on September 18, 2022

Comments

  • TheBlackBenzKid
    TheBlackBenzKid over 1 year

    Is there a shortcut for three code hexcodes, example, black can be wrote two ways

    .black{color:#000}
    .black{color:#000000}
    

    Can #DBDBDB this be wrote shorter? As #DBD does not work.

    Also what is faster, does it matter, I notice Firebug spits colors and some other vars in case sensitive format. Does it matter? Is it faster to have everything lowercase so the browser and user can load and render faster?

    .webform{color:#dbdbdb}
    .WebForm{color:#DBDBDB}
    
    • Bojangles
      Bojangles almost 12 years
      Both cases will have negligable differences in performance; every colour format is parsed into an internal memory structure by the browser anyway. Tools like Firebug read this and output a re-formatted version of that data. #DBD expands to #DDBBDD which is why it might not be giving the results you expect.
    • Luka Rahne
      Luka Rahne almost 12 years
      Have you turned off your java script?
  • TheBlackBenzKid
    TheBlackBenzKid almost 12 years
    If you consider things like Mobile devices "micro-optimising" is a small piece of the pie which will equate to overall improvement. Especially if 100kb CSS file becomes 35kb. Thanks for the comments.
  • Quentin
    Quentin almost 12 years
    A capital letter takes up the same number of bytes as a lower case letter.
  • TheBlackBenzKid
    TheBlackBenzKid almost 12 years
    OK. That is what I wanted to know - if example, The Webkit or browser engines covert this - it does not matter know as your answer is sufficient and the reduction must come from #000000 into #000 and the like
  • RichardTowers
    RichardTowers almost 12 years
    If you're worried about the size of your CSS, use a minifier. Most of these will shorten colours where possible. There's almost never a reason for a human to think about micro-optimisations on this level. "About 97% of the time: premature optimization is the root of all evil."
  • Mohammadreza Esmaeeli
    Mohammadreza Esmaeeli almost 7 years
    i changed generated link from bad seo structure to seo friendly structure and it works
  • Mohammadreza Esmaeeli
    Mohammadreza Esmaeeli almost 7 years
    so helpfull...another thing..sorry for my english..i can't speak well...how ever thanks god you guys are here :)
  • halfbit
    halfbit about 5 years
    Thanks. I had to add RewriteCond %{ENV:REDIRECT_STATUS} ^$ to prevent both rules being somehow strangely mixed together (like if L was not being considered). (+1)
  • MrWhite
    MrWhite about 5 years
    @MartinPrikryl Yes, thanks, missed that! That condition is required to prevent the rewritten URL being redirected and causing a redirect loop. We only want to redirect the initial request. I've updated my answer and added a bit of explanation in that regard. (Also noticed a typo in the query string that had unfortunately propagated through copy/paste - fixed that.)