PHP & URL Rewriting - php

I need a little help figuring out what the following URL rewrite rule means. I can understant the first three lines, but I got stuck with the index.php/$1 part. What does exactly the / means in this rule? The only thing I would always expect to see after a file name would be a query-string separator (?). This is the first time I am seeing the / as a separator. What does it exactly mean?
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [PT,L]
</IfModule>

The <IfModule mod_rewrite.c>...</IfModule> block ensures that everything contained within that block is taken only into account if the mod_rewrite module is loaded. Otherwise you will either face a server error or all requests for URL rewriting will be ignored.
The following two lines are conditions for the RewriteRule line which follows them. It means that the RewriteRule will be evaluated only if these two conditions are met.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
These lines simply state that rewriting (RewriteRule line) will occur only if there are no existing files or folders on the server which match the URI. If they do exist then they will be served instead, unless there is some other directive that prevents it, otherwise rewriting will occur.
The last line will do the actual rewriting. It will take whatever is following the website domain name and append it to a rewritten request which will begin with index.php/.
Here is an example.
Lets say you make a request for example.com/example-page.html.
If there is no existing file or folder in the virtual hosts root folder named example-page.html the rewrite rule at the end will rewrite the request to look like example.com/index.php/example-page.html.
The main reason why applications rewrite requests like this is to ensure that they have a single point of entry, often called a bootstrap, which is considered to be a good practice from the security standpoint and also offers more granular control of requests.
Here is in my opinion a very good beginner friendly tutorial for mod_rewrite.

It's just rewritting the url name.
For example, this url:
http://www.example.com/something/else
Will be the same as:
http://www.example.com/index.php/something/else

Related

How to write .htaccess file to get everything after slash as parameter?

I have a URL i.e "www.mysite.com". I want to send parameters via url in following ways:
www.mysite.com/count
www.mysite.com/search_caption?query=huha
www.mysite.com/page=1
www.mysite.com/search_caption?query=huha&page=1
In each of these cases I want to load index.php page with parameters as follows for each case:
var_dump($_REQUEST) results into [count]
var_dump($_REQUEST) results into [query="huha"]
var_dump($_REQUEST) results into [page=1]
var_dump($_REQUEST) results into [query="huha",page=1]
How do I write .htaccess file to achieve this?
I am using this code but it is capturing only params after "?" and not everything after first slash
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^([^/]+)/?$ index.php?{REQUEST_FILENAME}=$1 [L,QSA]
RewriteRule .* /index.php [L]
Something like that should get close, though you really should think about those strange URL patterns instead of trying to fix them afterwards with rewriting...
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L,QSA]
RewriteRule ^count index.php?count=1 [L]
RewriteRule ^page/(.*)$ index.php?page=1 [L]
RewriteRule ^ index.php [L,QSA]
Some notes:
the first three RewriteRules are exceptions necessary because your given requests do not follow a sane and common pattern. They appear somewhat chaotically chosen.
this certainly is not free of issues, I did not test it, only typed it down.
this assumes the "page" example to be requested like as discussed in the comments.
index.php actually has to exist as a file, otherwise this will result in a rewrite loop
Given all that these rewritings should happen:
www.mysite.com/count => index.php?count=1
www.mysite.com/search_caption?query=huha => index.php?query=huha
www.mysite.com/page/1 => index.php?page=1
www.mysite.com/search_caption?query=huha&page=1 => index.php?query=huha&page=1
Also note that the rules above are written for .htaccess style files. To be used as normal rules, so inside the http servers host configuration, they would have to be written slightly different. You should only use .htaccess style files if you really, really have to, so if you have no access to the configuration files. You should always try to avoid those files if somehow possible. They are notoriously error prone, hard to setup and debug and really slow the server down. So if you have access to the http server configuration, then defines such rules in there instead.

Apache mod_rewrite module issue

I have the following code in my .htaccess.
RewriteEngine On
RewriteRule ^/(\w+)/?$ /?user=$1
I'm trying to rewrite
http://domain.com/?user=username into http://domain.com/username. Unfortunately this code doesn't rewrite anything. Please help
Note:
I checked phpinfo() and mod_rewrite is loaded.
Update
I need to get username from url like http://facebook.com/username. But this code rewrites every folder in root folder, so my /css folder become http://domain.com/css/?u=common. How to allow this code works only for http://domain.com/index.php
The mistake you are doing is the use of / in the beginning of the line ^/(\w+)/?$
rewrite rules strips off the / from the beginning of the pattern to be matched in .htaccess and directory context.
Try doing this:
RewriteEngine On
RewriteRule ^(\w+)/?$ /?user=$1
From RewriteRule Directive docs :
What is matched?
In VirtualHost context, The Pattern will initially be matched against the part of the URL after the hostname and port, and before the query string (e.g. "/app1/index.html").
In Directory and htaccess context, the Pattern will initially be matched against the filesystem path, after removing the prefix that lead the server to the current RewriteRule (e.g. "app1/index.html" or "index.html" depending on where the directives are defined).
If you wish to match against the hostname, port, or query string, use a RewriteCond with the %{HTTP_HOST}, %{SERVER_PORT}, or %{QUERY_STRING} variables respectively.
Edit: Answer updated as per OP's request:
Add this :
RewriteEngine On
#do nothig if URL is trying to access the folder CSS.
RewriteRule *css/* - [L]
#checks where the URL is a valid file/folder.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(\w+)/?$ /?user=$1
I think that you are doing it the right way round, but explained it the wrong way round!
Is the problem that you don't need the initial / as the URL passed to test doesn't include it!?
I suspect it should be RewriteRule ^(\w+)/?$ /?u=$1
Also, be careful you don't end up with a loop!

URL Rewrite rule in .htaccess for Root directory

I am using this rule to rewrite the link
RewriteEngine On
RewriteRule ^(.*)/(.*) show_cv.php?email=$1
It is working fine like if I write this url with last slash
www.mysite.com/letschat_2008#yahoo.com/ ----> index.php?email=letschat_2008#yahoo.com
But when I remove the last slash from the link www.mysite.com/letschat_2008#yahoo.com/ it shows error 404.
I wish the URL Rewrite rule would work for both with slash and without slash (/)
www.mysite.com/letschat_2008#yahoo.com/ ----> index.php?email=letschat_2008#yahoo.com
www.mysite.com/letschat_2008#yahoo.com ----> index.php?email=letschat_2008#yahoo.com
Your rules are looping, you need to make sure you are rewriting an email address, and add some conditions so that the rule doesn't get applied if it's accessing an existing resource:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([A-Za-z0-9_\-\#\.]+)/?$ /show_cv.php?email=$1 [L]
You should then be using the following rule:
RewriteRule ^(.*)/? show_cv.php?email=$1
I assume you note these rules in a .htaccess file, not in the server configuration when looking at your description ?
Rethink if you don-t want to put this into the server configuration. Apart from the usage of .htaccess files being harder to debug using rewrite rules in those files is more complex than in the server configuration. This is documented in mod_rewrites docs.
The reason for the behaviour is the different content of REQUEST_URI in both cases. Have a try checking this directly and you will see the problem. The whole part "letschat_2008#yahoo.com" is simply missing in that variable in case 2 (no "/"). To get this working you must use an additional rewriteCondition (also documented...). Something like these untested lines:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(.+)&
RewriteRule - show_cv.php?email=%1
(note the '%' instead of a '$' in the last line)

htaccess rewrite ".../pages/about.php" to ".../about"

I've searched and found a lot of questions on this site and elsewhere that are very similar, but I've tried implementing and modifying all the suggestions I've found and none of it works. I realize this is a very basic question an I am extremely frustrated because nothing I'm trying is working.
With that having been said... I am trying to organize my content pages within kurtiskronk.com/pages/... (e.g. kurtiskronk.com/pages/about.php)
What I want to do is make it so that I can simply link to kurtiskronk.com/about ... So how do I go about stripping "pages/" and ".php"? I don't have a ton of content pages, so it's not a big deal if I have to specify for each page, though something dynamic would be handy.
NOTES: I am using Rackspace Cloud hosting, and WordPress is installed in /blog. My phpinfo() can be seen at http://kurtiskronk.com/pages/phpinfo.php
This is my existing .htaccess file (in the root)
php_value register_globals "on"
Options +FollowSymLinks
RewriteEngine On
#301 redirect to domain without 'www.'
RewriteCond %{HTTP_HOST} ^www\.kurtiskronk\.com$ [NC]
RewriteRule ^(.*)$ http://kurtiskronk.com/$1 [R=301,NC]
RewriteBase /
RewriteCond %{ENV:PHP_DOCUMENT_ROOT}/pages/$1 -f
RewriteRule ^(.*)$ pages/$1 [L]
RewriteCond %{ENV:PHP_DOCUMENT_ROOT}/pages/$1.php -f
RewriteRule ^(.*)$ pages/$1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/ blog/index.php [L]
# PHP - MAIL
php_value mail.force_extra_parameters -kurtis#kurtiskronk.com
I tested and the rewrite works with the line below (/about as URL brings up file /pages/about.php), but then the homepage gives a 500 Internal Server Error:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /pages/$1.php [L]
So I'm still sort of in the same boat as before, and as a follow-up, possibly more difficult question, if you go to http://kurtiskronk.com/weddings I am using SlideShowPro (flash) w/ SSP Director (self-hosted) as the back-end for it. When it pulls up a new image, it adds the following after /weddings ... "#id=album-152&num=content-9698"
There are four sections of the portfolio
# Homepage (kurtiskronk.com) id=album-148 ($id is constant for this section)
# Weddings (/weddings) id=album-152 ($id is constant for this section)
# Portraits (/portraits) id=album-151 ($id is constant for this section)
# Commercial (/commercial) id=album-150 ($id is constant for this section)
Assuming we get kurtiskronk.com/weddings to rewrite successfully without breaking anything, how would we make the total URL something cleaner kurtiskronk.com/weddings/9698 since the $num is the only thing that will change within a given section?
Kurtis, thanks for the extra information. It's a lot easier to give a specific answer to this.
My first comment is that you need to separate out in your thinking URI space -- that is what URIs you want your users to type into their browser -- and filesystem space -- what physical files you want to map to. Some of your mappings are URI->URI and some are URI->FS
For example you want to issue a permanent redirect of www.kurtiskronk.com/* to kurtiskronk.com/*. Assuming that you only server the base and www subdomains from this tree, then this cond/rule pair should come first, so that you can assume that all other rules only refer to kurtiskronk.com.
Next, you need to review the RewiteBase documentation. .htaccess files are processed in what Apache calls a Per-Directory context and this directive tells the rewrite engine what to assume as the URI base which got to this directory and .htaccess file. From what I gather, your blog is installed in docroot/blog (in the filesystem, and that you want to get to directory by typing in http://kurtiskronk.com/blog/ but that this .htaccess file is for the root folder -- that is the base should be (this goes before the www mapping rule)
DirectorySlash On
DirectoryIndex index.php
RewriteBase /
#301 redirect to domain without 'www.'
RewriteCond %{HTTP_HOST} ^www\.kurtiskronk\.com$ [NC]
RewriteRule ^(.*)$ http://kurtiskronk.com/$1 [R=301,NC]
You can add some field dumps look for REDIRECT_* in the Server or Environment table in the phpinfo O/P to see if these are sensible. For example:
RewriteWrite ^(.*)$ - \
[E=TESTDR:%{DOCUMENT_ROOT}/pages/$1.php,E=TESTPDR:%{DOCUMENT_ROOT}/pages/$1.php]
Your next rule is that if the file exists in the subdirectory pages then use it:
RewriteCond %{DOCUMENT_ROOT}/pages/$1 -f
RewriteRule ^(.*)$ pages/$1 [NS,L]
[Note that some shared service sites don't set up DOCUMENT_ROOT properly for the rewrite engine so you may need to run a variableinfo script (<?php phpinfo(INFO_ENVIRONMENT | INFO_VARIABLES); to see if it sets up alternatives. On your site you have to use %{ENV:PHP_DOCUMENT_ROOT} instead.]
Your next rule is that if the file exists, but with the extension .php in the subdirectory pages then use it:
RewriteCond %{DOCUMENT_ROOT}/pages/$1.php -f
RewriteRule ^(.*)$ pages/$1.php [NS,L]
Now redirect any blog references to the blog subdirectory unless the URI maps to a real file (e.g. the blog stylesheets and your uploads.)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/ blog/index.php [L]
A complication here is that WP may be using a poorly documented Apache feature call Path Info that is a script can act as a pseudo directory so http://kurtiskronk.com/blog/tag/downtown/ is redirected to docroot/blog/index.php/tag/downtown/ which is then executed by `docroot/blog/index.php using /tag/downtown/ as the PATH_INFO. But this is one for Wordpress experts to comment on. If this last rule doesn't work then try:
RewriteRule ^blog/(.*) blog/index.php/$1 [L]
PS. I like your site. I wish I was that young again :(
Postscript
When you say "it doesn't work", what doesn't with this .htaccess?
http://kurtiskronk.com/phpinfo,
http://kurtiskronk.com/phpinfo.php,
http://kurtiskronk.comblog/tag/downtown/
It's just that these rules work for these tests (with domain swapped) on mine. (One way is to move or copy the above variableinfo.php to the various subdirectories. If necessary temporarily rename the index.php to index.php.keep, say, and copy the variableinfo.php to the index.php file. You can now enter the various URI test patterns and see what is happening. Look for the REDIRECT_* fields in the phpinfo output, and the SCRIPT_NAME will tell you which is being executed. You can add more {E=...] flags to examine the various pattern results. (Remember that these only get assigned if the rule is a match.
Lastly note the changes above especially the additional NS flags. For some reason mod_rewrite was going directly into a subquery which was resulting in redirect: being dumped into the file pattern. I've had a look at the Apache code and this is a internal botch to flag that further redirection needs to take place (which then replaces this or backs out). However this open bug indicates that this backout can be missed in sub-queries and maybe that's what is happening here. Certainly adding the NS flas cured the problem on my test environment.
PS. Note the added explicit DirectoryIndex directive and also that whilst http://kurtiskronk.com will run the root index.php, the explicit /index.php version will run the one in pages, because that's what your rules say.
Here is a simple solution. You can use it apache conf file(s) or in .htaccess (easier to set up when you're trying).
mod_rewrite has to be enabled.
For example, use .htaccess in your DocumentRoot with:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /pages/$1.php [L]
It will redirect /about to /pages/about.php, and any other page.
The "RewriteCond" part is to authorize access to an existing file (eg: if you had an "about" file at the root of your site, then it will be served, instead of redirecting to /pages/about.php).
Options +FollowSymLinks
RewriteEngine On
RewriteRule /([0-9]+)$ /pages/$1.php [L]
Put something like this in your .htaccess file. I guess that is what you want.
Juest a redirect from a simple url to a longer url.

.htacces to capture the page name and send it as a get method

I am trying to capture a url such as
http://www.mysite.com/somepage.php?sometext=somevalue
and redirect it to.
http://www.mysite.com/index.php?page=somepage.php&sometext=somevalue
I tried searching for such .htaccess online, but couldn't find it.
Can you please help me?
I'm quite sure this is a duplicate, but I'm having a bit of an issue finding it/them [Edit: I found one, though possibly not the best example].
Anyway, this is a fairly standard problem resolved with fairly standard code:
RewriteRule ^(.*)$ index.php?get=$1 [L,QSA]
The RewriteRule captures the entire request as $1, and passes it to index.php as the page GET parameter.
The [QSA] flag on the end says to take any existing GET parameters (sometext=somevalue in your example), and add them as additional GET parameters on the new request. (The [L] flag just says that this should be the last rule executed.)
Note that this will also redirect requests for things like images or CSS files, so it's good to add the following lines directly before this rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
These lines say "if the request is for a file or directory that actually exists, don't process the rule." That way, requests for real files will be served directly by Apache, rather than being handled (or more likely, mishandled) by your PHP script.
RewriteRule ^(.*).php?sometext=(.*)$ index.php?page=$1.php&sometext=$2 [QSA,L] #rewrite
RewriteRule ^(.*).php?sometext=(.*)$ http://www.mysite.com/index.php?page=$1.php&sometext=$2 [R=301,L] #redirect

Categories