This should be simple but I cannot figure it out. I have this very simple mod_rewrite rule and it just doesn't want to work. This is the entire contents of the .htaccess file.
RewriteEngine On
RewriteRule ^([A-Za-z0-9-_/\.]+)/?$ index.php?page=$1 [L]
If I call the URL domain.com/foo it should rewrite it to index.php?page=foo. But instead, it rewrites it to index.php?page=index.php. I have tried multiple URLs:
index.php?page=foo
index.php
/foo
/
In all cases, PHP acts as if 'page' is set to "index.php". It isn't a fault with index.php because I replaced the entire contents of index.php with a script that simple echoed the value of 'page' and it still comes out as index.php.
Really lost where I'm going wrong here, any help would be awesome!
Thanks
Adrian
Any reason you can't use something simpler, such as:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1 [L]
If you're trying to keep existing pages from being re-written, then the !-f will take care of that (if file does not exist and if directory does not exist, then re-write)
I think this is what your looking for. Unfortunately it doesn't really work well if the URL has other GET arguments (IE, /some/url/path?page=1).
RewriteEngine On
RewriteRule ^(.*)$ index.php?page=$1 [L]
Better idea.
RewriteEngine On
RewriteRule ^(.*)$ index.php [L,QSA]
The QSA flag will forward the GET params and then in index.php use $_SERVER['REQUEST_URI'] and parse_url to route the request.
From http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html:
'qsappend|QSA' (query string append)
This flag forces the rewriting engine to append a query string part
in the substitution string to the existing one instead of replacing it.
Use this when you want to add more data to the query string via a rewrite rule.
Related
So I've found this interesting question on making the question mark symbol appear on $_GET variable after using rewrite rules.
However, as much as I've tried to accomplish this myself, I didn't quite understand how it works to have the same result on my website.
Here's my rewrite rule:
RewriteRule ^(.+)$ index.php?uri=$1 [QSA,L]
This basically allows me to route users to specific places without hard coding each page on my htaccess file, so if a user goes to /about/contact page, he's actually going to index.php?uri=/about/contact.
The problem is that sometimes I WANT the question mark to be kept in $_GET. Let's say a topic title of "What's up?" then my url would search for a topic like /topic/what-s-up? and would match with what-s-up? in the database. But, right now, my $_GET variable stores just "what-s-up" (without the "?") and my database still stores "what-s-up?" (with the "?"), which would say that there's no topic with that title when there actually is.
How can I keep the question mark so /topic/what-s-up? still translates to /topic/what-s-up? in the query string?
EDIT: FULL .HTACCESS FILE FOR TEST PURPOSES
Options -Indexes
DirectoryIndex index.html index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?uri=$1 [QSA,L]
You can change your rule to this to capture optional ? in uri parameter:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s/+([^?]*\??\S*)\sHTTP [NC]
RewriteRule ^(.+)$ index.php?uri=%1 [QSA,L]
Since we want ? also to be captured we are using RewriteCond %{THE_REQUEST} since pattern in RewriteRule only matches REQUEST_URI. Since we are capturing value from RewriteCond hence we are using %1 instead of $1 as back-reference.
THE_REQUEST variable represents complete original request received by Apache from your browser and it doesn't get overwritten after execution of some rewrite rules. Example value of this variable is GET /index.php?id=123 HTTP/1.1
I know its late, but i used php urlencode() to pass the question mark, as it converts ? to %3F
Looking to rewrite a URL and can't seem to get it working.
Example URL:
http://www.example.com/find/agency.php?agency=33524&name=happy-example
Ideal, rewritten URL:
http://www.example.com/find/agency/happy-example
One of the many attempted rewrites:
RewriteRule ^/([.]+)/([.]+)$ agency.php?agency=$1&name=$2
RewriteRule ^/([.]+)/([.]+)/$ agency.php?agency=$1&name=$2
Even if the removal of the "agency=" variable isn't possible, I still can't seem to make this URL write out the variables - am I approaching the rewrite backwards?
Try using a rewrite condition to catch the query string before doing the rewrite.
For example something like:
RewriteCond %{QUERY_STRING} ^agency=33524&name=([^&]+)
RewriteRule ^find/agency.php$ find/agency/%1? [R=301]
There are several things wrong with your rule. However to get a URL like this.
http://www.example.com/find/33524/happy-example
You would need to use a rewrite like below.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^find/([^/]+)/([^/]+)/?$ /agency.php?agency=$1&name=$2 [L]
Use a lazy modifier for the symbol matching (currently ([.]+) will match everything )
RewriteRule ^/([.]+?)/([.]+?)$ agency.php?agency=$1&name=$2
RewriteRule ^/([.]+?)/([.]+?)/$ agency.php?agency=$1&name=$2
You can also combine these into one rule
RewriteRule ^/([.]+?)/([.]+?)[/]{0,1}$ agency.php?agency=$1&name=$2
This does not include whatever flags you would need depending on your particular case
So far, I have made my .htaccess to let me remove the ".php" extension, but that isn't enough for me. I want to be so that example.com/test?id=asdfjK could be able to be accessed as example.com/asdfjK. So that it accepts only the main php get argument in the URL (I don't know what to call them.
Here is my .htaccess file so far:
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_]+)$ index.php?page=$1
RewriteRule ^([a-zA-Z0-9_]+)/$ index.php?page=$1
RewriteRule ^([a-zA-Z0-9_]+)$ /image.php?ID=$1
RewriteRule ^([a-zA-Z0-9_]+)/$ /image.php?ID=$1
There's no way to differentiate between what gets sent to index.php and what gets sent to image.php. The patterns are identical, which means everything will match the first one and nothing will get routed to image.php. You've got to add something to the url so that you can match against it. Something like:
http://example.com/image/abcdefg123456
And that means the htaccess file would look something like:
RewriteEngine On
RewriteRule ^([a-zA-Z0-9]+)/?$ index.php?page=$1 [L,QSA]
RewriteRule ^image/([a-zA-Z0-9]+)/?$ image.php?page=$1 [L,QSA]
The PHP arguments after the question mark are called the "query string".
Try something like this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteRule ^([a-zA-Z0-9]+)$ /index.php?page=$1 [L]
This should redirect anything from:
http://example.com/abc123
To:
http://example.com/index.php?page=abc123
See also:
htaccess rewrite for query string
.htaccess rewrite query string as path
How to prevent infinite redirect loop on htaccess?
I have the following .htaccess rewrite problem. We have requests entering with multiple subdirectories and an .html file
for example dir1/file.html
or dir1/dir2/file.html
or dir1/dir2/dir3/file.html
or dir1/dir2/dir3/dir4/file.html
what we eventually need is a rewrite rule to
index.html?dir1=$1&dir2=$2&dir3=$3&dir4=$4&file=$5
(where dir2 to dir5 would be empty if path is too short)
Is there any way to do that directly in the .htaccess file, or is it necessary to handle it in php?
I will see if I can test this out, but this should work for the problem as your question states it:
RewriteRule ^/([a-z0-9]+)/?([^/]*)$ /index.php?dir1=$1&$2 [QSA]
RewriteRule ^/([a-z0-9]+)/([a-z0-9]+)/([a-z0-9]+)/([a-z0-9]+)/?$ /index.php?dir1=$1&dir2=$2&dir3=$3&dir4=$4 [L]
RewriteRule ^/([a-z0-9]+)/([a-z0-9]+)/([a-z0-9]+)/?$ /index.php?dir1=$1&dir2=$2&dir3=$3 [L]
RewriteRule ^/([a-z0-9]+)/([a-z0-9]+)/?$ /index.php?dir1=$1&dir2=$2 [L]
RewriteRule ^/([a-z0-9]+)/?$ /index.php?dir1=$1 [L]
I emphasize should because only you can really say what your site structure is & how this cascading ruleset would affect your application.
The regex used is fairly simple:
([a-z0-9]+)
That captures any directory name with letters & characters. If you want to capture—let’s say—underscores and dashes on top of that, it would change to something like:
([a-z0-9_-]+)
The first rewrite rule I have set—^/([a-z0-9]+)/?([^/]*)$—is to capture anything that comes after dir1 just in case there’s data to capture that is not a strict directory structure. You can comment that out if you wish. Just added it since that’s how I like to handle situations that need URL parsing like this.
Also, have you considered adding this to the rewrite rule? Perhaps at the top before the rules cascade in?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
I would suggest you this
http://domain/dir1-dir2-dir3-dir4-dir5-file.html
rules
RewriteEngine On
RewriteBase /
RewriteRule (.+)-(.+) $1/$2 [N]
you can even make it dynamic by adding these
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1
this is much cleaner.
UPDATE:
well I didn't mean you use the second part but anyways I explain what I meant, it's not wrong that people use QUERY STRING for passing path in URL but it's important how you do that like in this URL
http://domain/index.php?route=dir1/dir2/dir3/dir4/dir5/file.html
as you can see you will grab the path easily with just one GET variable and even handling of this in RewriteRule is much easier like
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1&%{QUERY_STRING} [L]
which will let you to have a URL like this
http://domain/dir1/dir2/dir3/.../file.html
and with any reason you may change those slash to hyphen or other acceptable chars which become like this
http://domain/dir1-dir2-dir3-dir4-dir5-dir6-dir7-file.html
and as I said it's more easier to pass the current QUERY_STRING which will look like this
http://domain/dir1-dir2-file.html?q=extra_query_value
and result in PHP if you dump $_GET will be:
q => 'extra_query_value'
route => 'dir1/dir2/file.html'
and finally in PHP you may easily explode them to have all folders' name by individual variable.
I am having a little issue forcing the .php file extension to be removed in the URL.
I am successfully able to remove .php file extension if user:
#Remove PHP if original request is /foo/bar.php
RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
RewriteRule ^(.*)\.php(\?.*)?$ $1$2 [R=301,L]
My goal is to get it also to remove the extension if:
# Remove PHP if original request is /foo.php/bar
I ask because right now a user can go to the URL and type http://www.site.com/contact.php/about and it will render my about page. My goal is force the removal of the .php and render:
http://www.site.com/contact/about
I was hoping to take the code I have above and add it to but I can not figure it out.
TIA
It looks like you got the removing part, but you're missing the internally rewriting part. What you have attempts to remove the php out of the URL and redirects the client to a URL without it. But your condition isn't matching requests, change it to:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ .*\.php.*$
RewriteRule ^(.*)\.php(.*)?$ /$1$2 [R=301,L]
Then you need to internally rewrite it back (don't redirect browser). So in the same htaccess file, add:
RewriteCond %{REQUEST_URI} ^/([^/]+)(.*)$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^([^/]+)(.*)$ /$1.php$2 [L]
the following .htaccess gives me the requested parameters, you can get "page"
AddDefaultCharset utf-8
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [L]
DirectoryIndex index.php
RewriteRule ^([a-zA-Z0-9_-]{3,20})/([^/]+)/([^/]+)?$ index\.php?page=$1&s=$2&o=$3 [L]
RewriteRule ^([a-zA-Z0-9_-]{3,20})/([^/]+)?$ index\.php?page=$1&s=$2 [L]
RewriteRule ^([a-zA-Z0-9_-]{3,20})/?$ index\.php?page=$1 [L]
RewriteRule ^([a-zA-Z0-9_-]{3,20})?$ index\.php?page=$1 [L]
ErrorDocument 404 /404
Get "page" parameter and then call it like this
include('inc/'.$_REQUEST['page'].'.php');
and remember to remove .php ext from your links
Replace your tow lines with this single one : (you have an error in your rule, that's why it is not detecting .php in the middle and you don't need the rewrite condition)
RewriteRule ^(.+)\.php(/.*)?$ /$1$2 [L,R=301]
My solution for these problems is to basically avoid using complex rewrite rules and do URL routing from the php side, via a simple front controller.
Write the following .htaccess file at the root of your website:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]
Then write an index.php file in the same directory.
In the index.php file, you can still get the whole URL information, and choose a PHP file to include based on this.
<?php
// urldecode and get rid of the query string, $_GET is still available
$url = urldecode(preg_replace('/\\?(.*)$/', '', $_SERVER['REQUEST_URI']));
if ($url == '/contact/about') {
include 'contact.php';
}
That example is extremely basic, and I am probably ignoring subtleties of your website's architecture, but this approach is much more viable in the long run, because you can really map any URL of your liking to PHP scripts without having to endure the complexity of mod_rewrite.
This is the pattern that has been adopted by virtually every existing PHP framework (at least the MVC ones).
An minimalist example of this approach can be found in the Slim micro framework: http://www.slimframework.com/