I am building a content management system to allow a companies staff members to be listed via category. Essentially, this is what I'm trying to accomplish:
There is a page called inside.php that contains 404, 500, etc. errors. We have a page called physicians.php that passes variables and displays specific information based on the variable so physicians.php?id=1 would display a specific category of staff members. Currently, when you go to http://website.com/physicians or http://website.com/physicians/ it redirects to http://website.com/physicians.php just fine, but the problem is that happens even if you type some variation of the word physicians. Example being that physiciansasfhouiae would still link to physicians.php where we want it to link to inside.php because it is technically a non-existing page.
Here is the rewrite code that I have now:
RewriteEngine on
#enables you to access PHP files with HTML extension
AddType application/x-httpd-php5 .html .htm
RewriteCond ${REQUEST_URI} ^.+$
RewriteRule ^detail/(css|js|img)/(.*)?$ /$1/$2 [L,QSA,R=301] [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
RewriteCond %{REQUEST_URI} physicians
RewriteRule .* physicians.php
RewriteRule ^physicians/((([a-zA-Z0-9_-]+)/?)*)$ physicians.php?id=$1 [NC,L]
RewriteRule ^((([a-zA-Z0-9_-]+)/?)*)$ inside.php?page=$1
You should start by deleting these 2 lines:
RewriteCond %{REQUEST_URI} physicians
RewriteRule .* physicians.php
Not only are these 2 lines not necessary due to the RewriteRule that's already below them, but they're causing the main problem you're noticing. Those 2 lines match any URL with the substring "physicians" in it, which is not quite what you want. So you need to make your matching pattern more specific; thankfully, the next RewriteRule line is already doing that:
RewriteRule ^physicians/((([a-zA-Z0-9_-]+)/?)*)$ physicians.php?id=$1 [NC,L]
That line is really all you need to accomplish what you want. It tells Apache to only match the word "physicians" if it's the first word of the URL and ends in a slash (i.e. the whole, exact word "physicians"), which won't match misspellings like "physiciansasfhouiae".
But as a suggestion, I would tweak it slightly to make the optional trailing slash still match, and remove the slashes from the ID parameter:
RewriteRule ^physicians(/((([a-zA-Z0-9_-]+)/?)*))?$ physicians.php?id=$4 [NC,L]
So this will send all these variations to physicians.php:
/physicians
/physicians/
/physicians/abc123
/physicians/abc123/
And the ID parameter will equal abc123 (if it's provided). All other requests will go to inside.php, even if the URL contains a variation of "physicians".
Related
Before anyone comments, I know there are a lot of posts created on this topic, but none of them seem to solve my problem, that is why I have started this thread.
So, I have a page in my website called project.php which is used in GET query like so: project.php?id=12 I want to have a .htaccess file that converts the given URL into localhost/MyWeb/project/id/12/. I've literally followed every single post regarding that topic but none of them seem to work.
Also, along with that, I want all my .php and .html files to be shown just with their names, i.e localhost/MyWeb/index.php/ becomes localhost/MyWeb/index/ and localhost/MyWeb/sub1/sub2.php becomes localhost/MyWeb/sub1/sub2/.
EDIT:
The reason why I did not add my work in first place was because I didn't think it would be any helpful. But here it is:
RewriteEngine On
RewriteRule ^([0-9]+)$ project.php?id=$1
RewriteRule ^([0-9]+)/$ project.php?page=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
RewriteRule ^([^\.]+)$ $1.html [NC,L]
Firstly, you are operating out of a sub-directory (MyWeb), which means you need to set a RewriteBase. Also, you need to ensure that your .htaccess file is placed inside that sub-directory, and not in the localhost document root.
So, below RewriteEngine on, insert the folloeing line:
RewriteBase /MyWeb/
Next, you stated that you want to convert project.php?id={id} to project/id/{id}, but your code omits the /id/ segment. I also noticed that you have two rules, and that the second one contradicts your question, so I am only going to show you the change you need to make for the first rule, until such time as you clarify what the second rule is for.
To make the project URI work, change the very first rule to:
RewriteRule ^project/id/([0-9]+)/?$ project.php?id=$1 [QSA,L]
This will match the URI you want, with an optional trailing slash. I've also added the QSA flag which appends any extra query string parameters to the rewitten URI, as well as the L flag which stops processing if the rule is matched.
Next, to omit the .php or .html from your URIs, change the last three lines to the following:
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([^\.]+)$ $1.php [L]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^\.]+)$ $1.html [L]
When you make a request to localhost/MyWeb/index, Apache will check to see if localhost/MyWeb/index.php or localhost/MyWeb/index.html exist, and will then serve whichever one it finds first.
If you have both the PHP and HTML files, then the PHP one will be served, and not the HTML one. If you prefer to serve HTML files, then swap the two blocks around.
Unfortunately, I don't know of a good way to force a trailing slash for these, specifically because of the condition that checks for their existence. In other words, it won't work if you request sub2/, with the trailins slash because it would need to check if sub2/.php exists, which it does not.
Update: For added benefit, place these two blocks just below the new RewriteBase you set earlier to redirect the old URIs to the new ones whilst allowing the rewrites to the new URIs to still work:
RewriteCond %{THE_REQUEST} \/project\.php\?id=([0-9]+) [NC]
RewriteRule ^ project/id/%1/ [R=302,L,QSD]
RewriteCond %{THE_REQUEST} \/MyWeb/(.+)\.(php|html)
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ %1 [R=302,L]
For reference, here's the complete file: http://hastebin.com/gacapesoqe.rb
My goal is to make some friendly URL's using .htaccess. I need a mod_rewrite (for .htaccess) solution that allows me to have URLs like:
http://www.example.com/admin/lots -> /admin/lots/index.php
http://www.example.com/admin/lots/edit/1 -> /admin/lots/edit.php?id=1
http://www.example.com/admin/lots/view/1 -> /admin/lots/view.php?id=1
http://www.example.com/admin/lots/view/more/1 -> /admin/lots/view/more.php?id=1
http://www.example.com/admin/settings -> /admin/settings/index.php
http://www.example.com/admin/settings/edit/1 -> /admin/settings/edit.php?id=1
http://www.example.com/admin/project/status/edit/1 -> /admin/project/status/edit.php?id=1
There may be 1 to 10 directory levels with some of the URLs. It's highly unlikely, but if this RewriteCond/Rule could be expandable, that'd be great.
However, the "edit", the "id", and file names may be different. I think that explaining this is very hard to achieve especially because of the hundreds of possibilities.
Basically, I'd like to be shown the file if it exists, and there is nothing else after the file name in the url. If it's a file and has more after the file name, assume it's a variable. If it's a directory with nothing else after it, I'd prefer if it could go to the directory index (index.php in this case). If it's a directory with a file name after it, I'd like to be shown that file.
Keep in mind that if a part of the URL is neither a directory or a file, assume it is part of the query, such as ?id=1
If necessary, I can put it in the server config, however, I'd like to keep it stupid simple.
I recognize this URL pattern from Zend Framework. How Zend Framework does it, is rewrite everything to an index.php, which bootstraps the application, and does the actual routing according to the routing configuration set in the application.
If this is only in the /admin/ subdirectory, you could create the following rewrite (based on Zend's default .htaccess):
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^admin/.*$ - [NC,L] # Do not rewrite if it is an actual file/link/directory
RewriteRule ^admin/.*$ /admin/router.php [NC,L] # Rewrite to the router.php
And in the router.php, you can use the $_SERVER['REQUEST_URI'] to parse the URL, set variables in the $_SERVER['QUERY_STRING'], and include the proper PHP for the given URL, for example.
For the RewriteCond usage, check: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritecond
Let's start
Firstly, you'll need to put the following code in a file named .htaccess, in whichever directory you are dealing with:
RewriteEngine on
Now the mod_rewrite module has been turned on, and is ready to accept further instructions. The RewriteRule command is the root of the module, which tells mod_rewrite what to do. Here is its syntax:
RewriteRule Pattern Substitute (Optional Flags)
Here's an example:
RewriteRule /articles/([0-9]+) /articles.php?id=$1
This will replace http://www.yoursite.com/articles/1/ with
http://www.yoursite.com/articles.php?id=1.
You don't have to limit yourself to numbers either, you can use [a-z] or [A-Z] too!
Here are some flags you can use:
f: send a 403 forbidden error to the browser
NC: make the rule case-insensitive
g: send a 410 gone error to the browser
Not only can you rewrite URLs using rules, but you can also add conditions to these rules, so they won't be executed in every case:
RewriteCond Test Condition
Here's an example of what you can do with conditions:
RewriteCond %{HTTP_USER_AGENT} ^Opera.*
RewriteRule ^/$ /index_opera.php [L]
RewriteCond %{HTTP_USER_AGENT} ^Netscape.*
RewriteRule ^/$ /index_netscape.php [L]
RewriteRule ^/$ /index.php [L]
This will load a special page for Opera and Netscape, and load a default page for people not using Netscape. Here are some variables you can use in your conditions:
HTTP_USER_AGENT (browser)
HTTP_REFERER (referring page)
HTTP_HOST (domain name - yoursite.domain.com)
TIME, TIME_YEAR, TIME_DAY, TIME_HOUR, TIME_MIN, TIME_SEC
Get to work!
Now that I've (hopefully) wet your appetite, you can get working on some great uses of mod_rewrite. Here are some examples of what can be achieved:
/books/456/ » /index.php?mode=books&id=456
/books/456/buy » /index.php?mode=buy&id=456
/book_456.html » /index.php?book=456
... and Create beautiful url’s with mod_rewrite
The Apache rewrite engine is mainly used to turn dynamic url’s such as :
www.yoursite.com/product.php?id=123 into static and user friendly
url’s such as www.yoursite.com/product/123
RewriteEngine on
RewriteRule ^product/([^/.]+)/?$ product.php?id=$1 [L]
Another example, rewrite from:
www.yoursite.com/script.php?product=123 to
www.yoursite.com/cat/product/123/
RewriteRule cat/(.*)/(.*)/$ /script.php?$1=$2
You can use this code in your /admin/.htaccess:
RewriteEngine On
RewriteBase /admin/
RewriteCond %{ENV:REDIRECT_STATUS} 200 [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
RewriteRule ^([^/]+)/?$ $1/index.php [L]
RewriteRule ^(.+?)/([^/]+)/([^/]+)$ $1/$2.php?id=$3 [L]
i store uploaded files at /storage/ this way
public-adam-luki-uploads-123783.jpg
park-hanna-adel-propic-uploads-787689.jpg
the '-' count unknown because it slice the pic description
i want my users to be able to access it as
http://site.com/public/adam/luki/uploads/123783.jpg
http://site.com/park/hanna/adel/propic/uploads/787689.jpg
i think it is the same problem here
mod_rewrite with an unknown number of variables
but i can't do it because i'm new to mod_rewrite module
i hope you can help me guys with the right rewriterule
The question you link to doesn't actually do what you are trying to do (although the principle is the same) what they do is convert the url to GET variables.
If all you want to do is convert / to - then you can use a simple rewrite rule that will run in a loop:
ReWriteRule ^(.*)/(.*)$ $1-$2 [L]
There are of course a few caveats to that...
Firstly, even if you are trying to get to a real directory/file the rule will still switch out / and - and leave you with a 404. You can get around that by adding conditions; to stop it rewriting real files:
RewriteCond %{REQUEST_FILENAME} !-f
You would do better however to limit the matches to only images (jpgs):
RewriteCond %{REQUEST_FILENAME} !-f
ReWriteRule ^(.*)/(.*)\.jpg$ $1-$2.jpg [L]
Preferred Solution
ReWriteCond %{REQUEST_FILENAME} !-f
ReWriteRule ^images/(.*)/(.*)uploads[-/](\d+)\.jpg$ images/$1-$2uploads-$3.jpg [L]
RewriteCond %{REQUEST_FILENAME} !-f
ReWriteRule ^images/(.*)$ storage/$1 [L]
This solution requires you to use urls like:
http://site.com/images/park/hanna/adel/propic/uploads/787689.jpg
The pseudo directory images means you can be sure that the url is actually one that you want to redirect and it doesn't break other images/links on your site.
The above rules take a url (like the example above) and transforms it like so:
images/park/hanna/adel/propic/uploads/787689.jpg <--- Original
images/park-hanna/adel/propic/uploads-787689.jpg
images/park-hanna-adel/propic/uploads-787689.jpg
images/park-hanna-adel-propic/uploads-787689.jpg
images/park-hanna-adel-propic-uploads-787689.jpg
storage/park-hanna-adel-propic-uploads-787689.jpg <--- Final
I have created a login interface where user can register there username. Now i wanted to give each user a vanity url like, example.com/user. I am using .htaccess rewrite conditions and php for that. Everything is working fine except when i try a url like example.com/chat/xx it displays a profile page with "xx" id. Instead it should have thrown a 404 page(thats what i want). I want that vanity url thing only works if a user input "example.com/user" not in sub directory like "example.com/xyz/user". Is this possible ?
htaccess --
RewriteEngine on
RewriteCond %{REQUEST_FILENAME}.php -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^([^\.]+)$ $1.php [NC]
RewriteCond %{REQUEST_FILENAME} >""
RewriteRule ^([^\.]+)$ profile.php?id=$1 [L]
Php used --
if(isset($_GET['id']))
// fetching user data and displaying it
else
header(location:index.php);
Then you must match on an URL-path without slashes / only
RewriteEngine on
RewriteRule ^/?([^/\.]+)$ profile.php?id=$1 [L]
This regular expression ^([^\.]+)$ matches everything without a dot ., e.g.
a
bcd
hello/how/are/you
chat/xx
but it doesn't match
test.php
hello.world
chat/xx.bar
This one ^/?([^/\.]+)$ works the same, except it disallows slashes / too. I.e. it allows everything, except URL-paths, containing either dot . or slash /.
For more details on Apache's regular expressions, see Glossary - Regular Expression (Regex) and Rewrite Intro - Regular Expressions.
In my page I have a login folder. When I enter into domain.com/login/ it takes me correctly to the folder. When I write domain.com/login it also opens the page but the url changes into domain.com/login/?cname=login
My other main link is like domain.com/company and works correctly. However if i write domain.com/company/ it sais object not found.
How can I fix these?
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/$
RewriteCond %{REQUEST_URI} !^/domain.com/index.(php|html?)
# domain.com/login
RewriteRule ^/login?$ /domain.com/login/index.php
# domain.com/abc
RewriteRule ^([a-z0-9]+)?$ /domain.com/profile/company-profile.php?cname=$1 [NC,L]
It sound like you want to have domain.com/login/ or domain.com/login take you to the login folder.
The rule below will ensure that all of your folders end with a trailing slash and thus make domain.com/login work.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://domain.com/$1/ [L,R=301]
The next rule below will allow domain.com/company/ to work. In combination with the rule above, it will also ensure that domain.com/company continues to work.
RewriteRule ^company/$ profile/company-profile.php?cname=company [NC,L]
You should delete your other rules as they are incorrect.
Edit
Based on your last response modify the last rule to be
RewriteCond %{REQUEST_URI} !=/login/ [NC]
RewriteRule ^([a-z0-9]+)/$ profile/company-profile.php?cname=$1 [NC,L]
i.e. for all URI's except login do the rewrite company rule.
Make sure that you understand that any # of RewriteCond's only apply to the very next RewriteRule. I don't understand why you're matching against REQUEST_URI with a RewriteCond, rather than just matching it as part of the RewriteRule.
I also don't understand exactly what you're trying to accomplish with the ^/login?$ RewriteRule. I'm guessing the '?' needs to be escaped - otherwise, you're literally asking it to match against "/login" or "/logi".
Due to complications from the above concerns, I'm guessing your "domain.com/login" request is being handled by the 2nd RewriteRule which contains the "cname=", though I'm confused why you then don't see the "company-profile.php" as well (assuming maybe just an oversight in your question)?
After considering the above and trying to simplify this a little, I'm guessing everything should fall into place. If not, please comment back, and we'll see what we can do.