htaccess redirect with unique id to title - .htaccess

I have URL's like this:
http://www.example.com/en/product.php?id=23&t=page-title-here
I want change URL's to something like this :
http://www.example.com/en/product23/page-title-here/

Place the following in your /.htaccess file:
RewriteEngine on
# Step 1: Redirect file-based URIs to new 'pretty permalinks' and prevent looping
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{QUERY_STRING} ^id=(\d+)&t=([^/]+)$ [NC]
RewriteRule ^(en/product).php$ /$1%1/%2? [R=302,NE,L]
# Step 2: Rewrite above permalink to file-based URI
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en/product)(\d+)/([^/]+)/?$ /$1.php?id=$2&t=$3 [L,QSA]
Update: If you want to match multiple languages (per your comment below), you can use a non-capture group that checks for exactly two characters instead of just en:
# Use this rule in step 1 above
RewriteRule ^((?:[a-z]{2})/product).php$ /$1%1/%2? [R=302,NE,L]
# Use this rule in step 2 above
RewriteRule ^((?:[a-z]{2})/product)(\d+)/([^/]+)/?$ /$1.php?id=$2&t=$3 [L,QSA]

Related

htaccess redirecting to the wrong page when using multiple rewriterules

I have a htaccess file which looks like the following:
Options -Indexes
RewriteEngine On
# no php extension
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
# only allow rewriting to paths that dont exist
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# example.com/username
RewriteRule ^([\w\d_\-]+)/?$ profile.php?uid=$1 [L,QSA]
# example.com/username/$tab
RewriteRule ^([\w\d_\-]+)\/([\w]+)/?$ profile.php?uid=$1&tab=$2
# example.com/listen/$id
RewriteRule ^listen\/([\w\d_\-]+)?\/?([\w\d_\-]+)?$ track.php?id=$1&secret=$2 [L,QSA]
The way it is supposed to work is to redirect any URL looking like these:
1. example.com/example points to profile.php?id=example
or
2. example.com/example/tab points to profile.php?id=example&tab=tab
3. example.com/listen/example points to track.php?id=example
or
4. example.com/listen/example/code points to track.php?id=example&secret=code
The problem is that sometimes, a link which looks like the third one will point to the profile page. However, what's weirder, is that if example has a dash in it, it will point to the right place. This shouldn't be happening because my regex is matching after listen.
All help is appreciated.
Both of your listen/ rules should appear before other rules and moreover 2 RewriteCond are only being applied to next immediate RewriteRule.
You may use these rules to replace all of your code:
Options -Indexes
RewriteEngine On
# only allow rewriting to paths that don't exist
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# example.com/listen/$id
RewriteRule ^listen/([\w-]+)/?$ track.php?id=$1 [L,QSA,NC]
# example.com/listen/$id/secret
RewriteRule ^listen/([\w-]+)/([\w-]+)/?$ track.php?id=$1&secret=$2 [L,QSA,NC]
# no php extension
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
# example.com/username
RewriteRule ^([\w-]+)/?$ profile.php?uid=$1 [L,QSA]
# example.com/username/$tab
RewriteRule ^([\w-]+)/([\w-]+)/?$ profile.php?uid=$1&tab=$2 [L,QSA]
Also note that \w means [a-zA-Z0-9_] so no need to add \d_ in character class.

Rewrite and redirect with php variables

I am simply trying to rewrite automatically this:
From: mysite.com/channel.php?id=BBC&name=British Broadcasting Company &date=today
To: mysite.com/channel-britishbroadcastingcompany-today.html
I've tried with:
RewriteRule ^channel-(.*)-(.*)\.html$ /channel.php?id=1&name=$2&date=$3 [R]
But nothing happens.
Hope this simplest one will help you out. This will redirect if
1. REQUEST_URI is /channel.php
2. QUERY_STRING matches this pattern id=something&name=something&date=something
Redirect this to /channel-%1-%2.html here
1. %1 will hold value of name parameter
2. %2 will hold value of date parameter
RewriteEngine on
Options -MultiViews
RewriteCond %{REQUEST_URI} ^/channel\.php$
RewriteCond %{QUERY_STRING} id=.*?&name=(.*?)&date=(.*)
RewriteRule .* /channel-%1-%2.html? [R=301]
As per the requirement specified by OP to first redirect url on html page on the basis of some query parameters then rewriting the request on previous page. So the complete code of .htaccess will be like this.
RewriteEngine on
Options -MultiViews
RewriteCond %{REQUEST_URI} ^/channel\.php$
RewriteCond %{QUERY_STRING} id=.*?&name=(.*?)&date=(.*)
RewriteRule .* /channel-%1-%2? [R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/channel\-(.*?)\-(.*?)
RewriteRule .* /channel.php? [L]
Explanation of 2nd part which is added.
1. REQUEST_FILENAME if file does not exist as a file and directory.
2. REQUEST_URI If request_uri starts with such pattern channel-somewords-somewords
then rewrite request on /channel.php
If I understand the problem correctly, You currently have a file channel.php and what You want to achieve is get more "friendly" URLs for SEO and general aesthetics in the browser location bar but still have channel.php handle your requests.
If this is really the case then You need a two-way rewrite.
First, You need to take your original URL and redirect it to a new, pretty version.
Second, You need to rewrite this pretty URI internally and still feed it to channel.php behind the scenes.
RewriteEngine On
RewriteBase /
# This part rewrites channel.php?name=X&date=Y into channel-X-Y.html
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{QUERY_STRING} (.*\&)?name=([^&]+)\&date=([^&]+)(?:\&(.*))?
RewriteRule ^channel.php$ channel-%2-%3.html?%1%4 [R,L,NE]
# This part rewrites it back into channel.php but keeps the "friendly" URL visible
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^channel-(.*)-(.*).html$ channel.php?name=$1&date=$2 [L,QSA]
Note that the first rule-set limits the rewrite to method GET - otherwise You will lose any submitted POST data.
It also allows for any other query-string parameters to surround name and date (the rest of query-string parameters will pass-through to .html URI and then will be picked back up by channel.php)
Also note the ENV:REDIRECT_STATUS rule - this is crucial, without that part You'll be stuck in redirect loop.
See
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^([a-z0-9-_.]+)/?$ index.php?id=$1 [NC,L]
RewriteRule ^([a-z0-9-_.]+)/([a-z0-9]+)/?$ index.php?id=$1&goto=$2 [NC,L]
What it's going to do is check the index.php and replace to some like, site/dir/index.php to site/dir/namehere than in index.php you can use explode() to separate the values of current url ang get the variables
I am assuming you are asking for rewrite although you are using redirect flag in your current rules, and also assuming BBC to be static in id variable then try with below,
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^channel-([^/]+)-([^/]+).html$ channel.php?id=BBC&name=$1&date=$2 [L]

Rewrite two generic values to static

Hello I want to rewrite two values to static value on a link.
Sometimes link is like this: http://website.com/?s=page2
or like this: http://website.com/?m=page1&s=page2
I want to rewrite these links to these:
http://website.com/page2
http://website.com/page1/page2
You can use these 2 rules in your root .htaccess:
RewriteEngine On
# skip all files and directories from rewrite rules below
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# single parameter rule
RewriteRule ^([^/]+)/?$ ?s=$1 [L,QSA]
# two parameters rule
RewriteRule ^([^/]+)/([^/]+)/?$ ?m=$1&s=$2 [L,QSA]

.htaccess rewrite blank spaces with - ("%20" to "-")

I want to remove %20 on my link to - (dash),
My .htaccess is like that right now,
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ icerik.php?name=$1 [QSA,L]
For example,
site.com/vision-and-mision,
site.com/do-re-mi-fa-so-la-si.
Actually I searched something but the informations were very specific and I'm confused
Thank you.
You can use the following in your /.htaccess file:
RewriteEngine On
# Replace whitespace with hyphens, set the environment variable,
# and restart the rewriting process. This essentially loops
# until all whitespace has been converted.
RewriteRule ^([^\s]*)\s(.*)$ $1-$2 [E=whitespace:yes,N]
# Then, once that is done, check if the whitespace variable has
# been set and, if so, redirect to the new URI. This process ensures
# that the URI is rewritten in a loop *internally* so as to avoid
# multiple browser redirects.
RewriteCond %{ENV:whitespace} yes
RewriteRule (.*) /$1 [R=302,L]
Then add your rules afterwards:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /icerik.php?name=$1 [QSA,L]
If this is working for you, and you would like to make the redirects cached by browsers and search engines, change 302 to 301.

Rewriting urls using mod_rewrite : Error with multiple rules

I have following code in .htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)(/([^/]+))?(/(edit)+)(/([^/]+))?/?$ edit.php?secret=Y7qD7&category=$1&slug=$3&edit=$5&part=$7 [L]
RewriteRule ^([^/]+)(/([^/]+))?/?$ content.php?category=$1&slug=$3 [L]
RewriteRule ^(/)?$ content.php [L]
What I expect to achieve is
http://example.com/test/test1/edit/part to edit.php?category=test&slug=test1&edit=edit&part=part
http://example.com/test/edit/part to edit.php?category=test&slug=&edit=edit&part=part
(above rewrite is working as expected)
`http://example.com/test/test/` to `content.php?category=test&slug=test`
`http://example.com/test/` to `content.php?category=test&slug=`
(Please note that there is no "/edit/" & "/part/" in above 2 urls)
for above two rewrites, first one is working fine but the second one is not working as expected. The last one get rewrite to content.php?category=content.php&slug= which is not correct.
Also trailing slash should not make a difference for the rewrite.
Could somebody please show me what I'm doing wrong here?
I didn't check why the rule in your question doesn't work as expected, but you may try this instead:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/([^/]+)/?([^/]*)?/?([^/]*)?/?([^/]*)?/?
RewriteRule .* edit.php?key1=%1&key2=%2&key3=%3&key4=%4 [L]
Maps silently:
http://example.com/val1/ up to
http://example.com/val1/val2/val3/val4/ with or without trailing slashes
To:
http://example.com/edit.php?key1=val1&key2=val2&key3=val3&key4=val4
The maximum quantity of valN values passed in the incoming URL, is 4. The minimum is 1. That range can be adjusted modifying the rule, though.
When any valN is not present in the incoming URL, the value in the corresponding key-value pair in the query added to the substitution URL, will be empty.
However, the key will always be present in the query as all keys are fixed strings not passed by the incoming URL.
This rule-set is tested and working and it should be tested without any other rule that might get in conflict with it. I didn't check the other rules in the question and can't say if they work or if they could affect this one. That was not part of the question.
UPDATE
Redirecting to edit.php:
Mapping to edit.php is required only when there are 3 or 4 folders in the URL-path.
The modified rule-set is:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !edit\.php [NC]
RewriteCond %{REQUEST_URI} ^/([^/]+)/([^/]+)/([^/]+)/?([^/]*)?/?$ [NC]
RewriteRule .* edit.php?key1=%1&key2=%2&key3=%3&key4=%4 [L,QSA]
Maps silently:
http://example.com/val1/val2/val3/ up to
http://example.com/val1/val2/val3/val4/ with or without trailing slashes
To:
http://example.com/edit.php?key1=val1&key2=val2&key3=val3&key4=val4
The maximum quantity of valN values passed in the incoming URL, is 4. The minimum is 3.
Redirecting to content.php:
Mapping to content.php is very similar to the previous one, except is done only when the number of folders is 1 or 2.
So the rule-set is basically the same with less regex groups:
RewriteCond %{REQUEST_URI} !content\.php [NC]
RewriteCond %{REQUEST_URI} ^/([^/]+)/?([^/]*)?/?$ [NC]
RewriteRule .* content.php?key1=%1&key2=%2 [L,QSA]
Maps silently:
http://example.com/val1/ up to
http://example.com/val1/val2/ with or without trailing slashes
To:
http://example.com/content.php?key1=val1&key2=val2
The maximum quantity of valN values passed in the incoming URL, is 2. The minimum is 1.
The complete rule-set is like this:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !edit\.php [NC]
RewriteCond %{REQUEST_URI} ^/([^/]+)/([^/]+)/([^/]+)/?([^/]*)?/?$ [NC]
RewriteRule .* edit.php?key1=%1&key2=%2&key3=%3&key4=%4 [L,QSA]
RewriteCond %{REQUEST_URI} !content\.php [NC]
RewriteCond %{REQUEST_URI} ^/([^/]+)/?([^/]*)?/?$ [NC]
RewriteRule .* content.php?key1=%1&key2=%2 [L,QSA]
Hope I understood what you want.

Resources