I'm trying to create some nice urls for my php search pages.
my current code:
RewriteRule ^/search-jobs/?$ search-jobs.php [NC,L] # Search jobs page
RewriteRule ^/search-jobs/jobs-in-(.*)/?$ search-results.php?location=$1 [NC,L] # Search results locations page
matches /search-jobs with search-jobs.php, great
but it also matches /search-jobs/jobs-in-london to search-jobs.php, but I want it to match the second rule for search-results.php
Why is the first rule always used? and how to fix it?
EDIT:
none of the current answers have worked. I think my issue is that somewhere on my hosting (not accessible by me) there are some defaults set, as if i just go to /search-results, it will automatically use search-results.php file, although I have set nothing telling it to do so?
So, in theory, any /search-jobs(.*) query will automatically use search-jobs.php, seemingly regardless of any rules I create.
anyway, I rearranged my rules to the below.. and I still always hit search-jobs.php file:
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^/search-jobs/jobs-in-(.*)/?$ search-results.php?location=$1 [NC,L] # Search results locations page
RewriteRule ^/search-jobs/(.*)-jobs/?$ search-results.php?keywords=$1 [NC,L] # Search results keywords page
RewriteRule ^/search-jobs/?$ search-jobs.php [NC,L] # Search jobs page
Remove slash / from the beginning of request string like this:
RewriteRule ^search-jobs/jobs-in-(.*)/?$ search-results.php?location=$1 [NC,L] # Search results locations page
RewriteRule ^search-jobs/(.*)-jobs/?$ search-results.php?keywords=$1 [NC,L] # Search results keywords page
RewriteRule ^search-jobs/?$ search-jobs.php [NC,L] # Search jobs page
Put your second rule first, and also enclose your regexes in quotes.
That way when it matches ^/search-jobs/jobs-in(.*)/?$ the [L] flag says don't continue so it won't process ^/search-jobs/?$
Related
On the home page of my website, I have a guide that includes some links, and each redirects to a family guide page, all with the redirection by identification of each element of the guide, remaining as the link
https://example.com/family-guide/?id=4
Where '4' is the ID of the element.
I would like to leave like this:
https://example.com/family-guide/4
I tried to use mod_rewrite in the .htaccess file:
RewriteRule ^family-guide/([0-9] +)/([0-9a-zA-Z_-]+) family-guide/?Id=$1name=$2 [NC, L]
but nothing happens
Your rule has some spaces. Be careful because if there is a space between the flags [NC, L] the rule is not valid.
Another thing is that you want the url https://example.com/family-guide/4 to match a rule and your rule expects two parameters (id and name) while in this url there is only one.
I would use a couple of rules instead:
RewriteRule family-guide/([0-9]+)/([0-9a-zA-Z_-]+) family-guide/?id=$1&name=$2 [NC,L]
RewriteRule family-guide/([0-9]+) family-guide/?id=$1 [NC,L]
With this rules if you go to https://example.com/family-guide/4 you should be shown the content of https://example.com/family-guide/?id=4. And if you go to https://example.com/family-guide/4/whatever it will show you the content of https://example.com/family-guide/?id=4&name=whatever instead, which is what I understood you need.
Also, the rule order is important as if they were in the opposite order https://example.com/family-guide/4/whatever would match the other rule and show the content of https://example.com/family-guide/?id=4/whatever
I have a very small question. I created a .htaccess file that suppose to rewrite a condition example.com/user/foo/bar as example.com/user.php?username=$1&tab=$2 so username name will be foo and the viewing tab must be bar.
But when there is no bar data provided exactly like example.com/user/foo/ it goes to user with default tab (default tab is generated in script.php file).
But I saw some website that they can do it just like example.com/user/foo, without the / at of the line. When I do example.com/foo to go to user, it says page not found. My correspoding .htaccess line is:
RewriteEngine On
RewriteRule ^user/(.*)/(.*)$ user.php?username=$1&tab=$2 [L]
Please help me with this sitiation.
Your match rule is ^user/(.*)/(.*)$, which means that the second slash must be there (since it's specified), but the text afterwards is optional (since * matches zero or more characters).
Really, I'd add two rewrite rules to do both differently (and to prevent using complicated regex), e.g.
RewriteRule ^user/(.*)/(.*)$ user.php?username=$1&tab=$2 [L]
RewriteRule ^user/(.*) user.php?username=$1 [L]
Alternatively, you can make the 2nd parameter optional:
RewriteRule ^user/([^/]+)/?(?:(.*)|)$ user.php?username=$1&tab=$2 [L]
As long as you don't mind having no value for $_GET['tab']
I am trying to rewrite links on my site.
Possible links before rewrite and what I want to see after rewrite:
/index.pl?mode=users&action=add - /users/add/
/index.pl?mode=streets&action=edit&id=7 - /streets/edit/7
/index.pl?mode=users&action=info&id=7 - /users/info/7
etc
.htaccess content:
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.(jpe?g|gif|bmp|png|tiff|css|js)$ [NC]
RewriteRule ^([A-Za-z0-9-]+)/((edit|delete|info))/([0-9]+)$ index.pl?mode=$1&action=$2&id=$3 [L]
RewriteRule ^([A-Za-z0-9-]+)/((add))/?$ index.pl?mode=$1&action=$2 [L]
RewriteRule ^([A-Za-z0-9-]+)/?$ index.pl?mode=$1 [L]
/users/add/ or /street/add/ are working properly, but...
Problems:
/users/edit/xx - I can't accept ID in perl script. Why?
/users/info/xx - I can't even get to info section /?mode=users&action=info&id=7 page (it have to show blank table with wrong ID
Btw... My site has 'switch' structure. I mean if mode is users, then it load "users.pl", if mode=streets loading "streets.pl", etc. About 2nd problem - sure I have info section at users.pl! And link /?mode=users&action=info&id=7 work perfect.
p.s.: added php-tag because it is not 'perl' problem , but php is equal to perl, so php-followers can help me too
p.p.s.: sry for my not very good english.
You have too many parentheses, which makes your backreferences off-by-one:
RewriteRule ^([A-Za-z0-9-]+)/(edit|delete|info)/([0-9]+)$ index.pl?mode=$1&action=$2&id=$3 [L]
RewriteRule ^([A-Za-z0-9-]+)/(add)/?$ index.pl?mode=$1&action=$2 [L]
Those two rules had too many parentheses around the ((edit|delete|info)) and ((add)) (though the "add" isn't affected because $2 correctly backreferences it).
Friends I am newbie to .htaccess and Rewrite Rule and very puzzled about these rules. I am trying to execute these following lines for the index.php page.
When I write in url, one or two or three or four query arguments then it goes OK. Any of these pattern matches I collects query and proceed further in php. But when query arguments exceeds more than four arguments (say someone intentionally trying to give wrong urls) I want to redirect the page to homepage. I didn't found any solution anywhere on internet. Can anybody help me, how to do that. I desperately want a solution to do this project and in very urgent need. I read many articles but doesn't understand how to handle this problem. I'm executing these all tasks with XAMPP on Win 7. The patterns I am using are,
RewriteRule ^([a-zA-Z0-9_]+)/?$ index.php?levelone=$1 [NC]
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$ index.php?levelone=$1&leveltwo=$2 [NC]
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$ index.php?levelone=$1&leveltwo=$2&levelthree=$3 [NC]
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$ index.php?llevelone=$1&leveltwo=$2&levelthree=$3&levelfour=$4 [NC]
URL example :
(say localhost/myproject/index.php is my homepage)
localhost/myproject/levelone/
localhost/myproject/levelone/leveltwo/
localhost/myproject/levelone/leveltwo/levelthree/
localhost/myproject/levelone/leveltwo/levelthree/levelfour
When I use these four Urls then it's ok, but if I use
localhost/myproject/index.php/levelone/leveltwo/levelthree/levelfour/levelfive/levelsix/
then my index.php page return some html without style and layout, I trying many types of RewriteCond and commands in .htaccess but all in vain.
I want that query string arguments must be in the range from 1 to 4 if it exceeds the range say five arguments then page must redirect to homepage (/index.php) again otherwise match to pattern.
It would help me if anyone know if there is way to combine all these four long patterns in one short line for matching any of four.
This rewrite rule will only kick in if there is not a file or directory that already exists.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /path/to/index.php [L,QSA]
The -f flag will make the rewrite only kick in if the file doesn't exist, and the -d flag will ensure the rewrite won't kick in if a directory exists.
I suggest avoiding a redirect to the home page.
In index.php, display the home page content by default if none of the level variables are set.
Here's a one-line rule (maybe it can be simplified even more):
RewriteRule ^(?:([a-zA-Z0-9_]+)\/)?(?:([a-zA-Z0-9_]+)\/)?(?:([a-zA-Z0-9_]+)\/)?(?:([a-zA-Z0-9_]+)\/)?$ index.php?level1=$1&level2=$2&level3=$3&level4=$4 [L]
And the PHP:
$levels=array();
foreach (range(1,4) as $i) {
if (isset($_GET['level'.$i])) {$levels[$i]=$_GET['level'.$i];}
}
if (!empty($levels)) {
// show level content
} else {
// show home page
}
I have a site written in php which creates 'pretty' urls for each item (on category and search pages) like this,
mysite.com/category/slug-for-item-one/1
mysite.com/category/slug-for-item-two/2
The /category/ and /slug/ is dependent upon the numeric id of the item
I have mod_rewrite serve the actual content from urls like this:
mysite.com/view-item.php?id=1
mysite.com/view-item.php?id=2
The content for each item is retrieved using just the items id.
Here's my htaccess:
RewriteEngine on
RewriteRule ^([^/\.]+)/?$ view-item.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ view-item.php?pid=$2 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ view-item.php?id=$3 [L]
Everythings ok so far but, if someone lands on on a url like,
mysite.com/1
mysite.com/catey/slug-for-item-one/1
or
mysite.com/category/slug-item-one/1
the content is still served, but how can I automatically reset or redirect to the canonical version of the url, to:
mysite.com/category/slug-for-item-one/1
I've searched SO and google extensively for an answer, but no luck. I've only used mod_rewrite for simple redirects such as from without www. to with www. and my understanding is tentative thus I'm struggling to understand how to proceed at the moment.
Can anyone point me in the right direction?
Thank you everyone for your help. Much appreciated. I'm working on an implementation of Jon Lin's answer as I'm more familiar with using php/mysql databases and understand how and why it should work. I aim to be done by Friday and will update this page when finished. Many thanks, Karl.
* UPDATE *
I have implemented Jon Lin's answer and now my 'pretty' urls, when mistyped are now redirected to the correct or 'canonical' url just as on SO. Thank you Jon and everyone who contributed!
I think you are going to need two sets of rewrite rules to accomplish this.
The first set of rules would be used to send 301 redirects to the client to ensure they are referencing the canonical URLs:
RewriteRule ^/1 /category/slug-for-item-one/1 [R=301,L]
Then a second set of rules that use passthroughs [PT] to serve up the content:
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ view-item.php?id=$3 [PT,L]
Or something along those lines...
Easy as pie:
RewriteCond %{REQUEST_URI} ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$
RewriteCond %1 !category
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$ $1/category/$3/
This means: if the request does look like category/slug-for-item-two/2 and the first match is not the word category (whatever it is) then force the redirect to category/slug-for-item-two/2
Please tell me if it works
Update (after your comment):
Here's what should work:
Create 2 map files (see mod_rewrite.html#rewritemap to learn how to do).
Create a mapfile where you put all the categories you need:
RewriteMap mapcategories \
dbm:/web/htdocs/yoursite/rewriterules/categories.map
In the mapfile create simple entries like:
shirts 1
hats 2
condoms 3
vegetables 4
mother-in-laws 5
...
Now do another file with the opposite:
RewriteMap mapcategoriesreverse \
dbm:/web/htdocs/yoursite/rewriterules/categoriesreverse.map
In the mapfile create simple entries like:
1 shirts
2 hats
3 condoms
4 vegetables
5 mother-in-laws
...
Then here you go for the hard part:
RewriteCond %{REQUEST_URI} ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$
# The following rule will try to search into the categories map file
# and if not found, assign CATEGORY to "notfound"
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$ \
- [QSA,E=CATEGORY:${mapcategories:%1|notfound}]
# if the CATEGORY is not empty and is not found:
RewriteCond %{ENV:CATEGORY} notfound
# do a reverse map to get the *real* category:
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$ \
- [QSA,E=CATEGORYREVERSE:${mapcategoriesreverse:%1|notfound}]
# if the CATEGORYREVERSE is not empty and is not found:
RewriteCond %{ENV:CATEGORYREVERSE} notfound
# this should never happen => 404:
RewriteRule . - [R=404,L]
# If reach here = if the CATEGORYREVERSE is not empty
# this means it has properly been found:
RewriteCond %{ENV:CATEGORYREVERSE} !^$
# Inject the right category:
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$ \
%{ENV:CATEGORYREVERSE}/$2/$3/ [QSA]
This way everything is dynamic but it's (much) longer and (a little bit) more complex.
Olivier
This is probably something you want to implement in your view-item.php instead of trying to use mod_rewrite. When you are generating the links internally within your content, you can use the ID's to lookup categories and slugs. This would be how you normally go about generating one of the pretty SEO friendly links.
You first need pass the category and slug into the request. Something along the lines of:
RewriteEngine on
RewriteRule ^([^/\.]+)/?$ view-item.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ view-item.php?pid=$2&cat=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ view-item.php?id=$3&cat=$1&slug=$2 [L]
At the top of your view-item.php, simply check if the cat and slug parameters exist, compare them to the actual category and slug when you do the lookup for the id. If one of them doesn't match (or is missing, if you want), then redirect the browser to the correct link with the correct category and slug using the header() function:
header('HTTP/1.1 301 Moved Permanently');
header("Location: " . $correct_url);
exit();
After they get redirected, the process repeats itself, but this time, view-item.php sees the correct category and slug so the page gets served like normal.