I would like to rewrite www.mysite.com/a/b/slug to www.mysite.com/a/b/index.php?id=slug.
I am trying to capture the last segment of the path i.e. slug and use it in the query string -- similar to this example.
So I have the following lines in my .htaccess sitting in my public_html folder:
RewriteEngine on
RewriteRule ^a/b/([^/]+) a/b/index.php?id=$1 [L]
In my a/b/index.php, when I go to www.site.com/a/b/slug, $_GET['id'] returns index.php opposed to slug. I am not sure why.
How can I capture the last segment and use it in the query string?
You need to add rewrite conditions in your .htaccess - at the moment, it is attempting to rewrite /a/b/index.php as well!
Try adding RewriteCond %{REQUEST_FILENAME} !-f and RewriteCond %{REQUEST_FILENAME} !-d
Related
Let's call my site:
www.example.com
and I have a PHP file like this:
www.example.com/product.php?id=50
I would like to access it by using
www.example.com/product/50
but ALSO, very important, I have several subdirectories like
www.example.com/subsite/product.php?id=50
www.example.com/subsubsite/product.php?id=50
That must become
www.example.com/subsite/product/50
www.example.com/subsubsite/product/50
How can I solve it at best with PHP and .htaccess using mod_rewrite?
I banged my head with other questions like this one but to no avail.
I can't seem to find a solution that works flawlessly, taking care of all imported files like CSS, JS and PHP classes.
Ok so this might not be the complete answer but should help you find your way.
You can use regex to match your desired path pattern. So for example your htaccess might look something like...
# Check if module is installed
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Check query for matching pattern and pass id, but also append additional query strings
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\/]+\/)?product\/([0-9]+)$ /$1product.php?id=$2 [L,QSA]
# If not file or directory on server, send to 404.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /404.php [L]
</IfModule>
And what this does is...
1. Match the uri with a regex pattern
Regex: ^([^\/]+\/)?product\/([0-9]+)$
^ - Start of string.
([^\/]+\/)? - matches any directory (if exists) and stores it for reuse.
product\/([0-9]+) - Your desired path e.g. product/50 and stores the number "id" for reuse.
$ - End of string.
2. Pass captured directory and id to our file
Like so: /$1product.php?id=$2 [L,QSA]
$1 is our directory name including the trailing slash e.g. subsubsite/
$2 is our product id e.g. 50
[L,QSA] The QSA flag means we can access additional query string parameters e.g. /product/50?show=all&updated=1. More about flags can be found here http://httpd.apache.org/docs/current/rewrite/flags.html#flag_qsa
3. 404 anything not matching
Like so:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /404.php [L]
!-f If request is not a file
!-d If request is not a directory
/404.php The file used for presenting a 404 error.
Getting the id...
With the above, you can get the ID within your product.php file like so:
$id = (int)$_GET[ 'id' ];
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
UPDATE: This works:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} ^[A-Z]+\ ([^\s]+)
RewriteRule (.+) /index.cfm?event=checkuri&uri=%1 [QSA]
Some background...
So we already have a catchall redirect in our .htaccess file which is this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) /index.cfm?event=checkuri&uri=$1
This ties into a database table that checks the URI for a match. so if we just moved a site that used to have this page:
/some-awesome-article.html
Onto our system, and the new address is
/awesome-article/12442
and someone tried to access the old URI, our system would check for this, find a match, and forward them to the new home: /awesome-article/12442
This system works awesome, with one exception. If the URI is something like /index.php?id=123412 then the whole system falls apart. In fact /index.php/whatever won't work either.
Everything else works except for this. We do not use PHP for our web application (although support says its in an admin console on the server somewhere).
So basically what I need is if index.php is detected anywhere it will forward the URI to our
existing system:
How can i modify this to fix it?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) /index.cfm?event=checkuri&uri=$1
Try changing your code to:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) /index.cfm?event=checkuri&uri=$1 [L,QSA]
QSA is for Query String Append that will make sure to append existing query parameters with the new ones.
Rewriting with mod_rewrite does not work on the full URL. In fact, the regex in the RewriteRule does only get the path and file, but not the query string. And so the backreference $1 will only contain "index.php" and nothing else.
Additionally, the RewriteRule does change the query string because there is one in the target pattern. Because the flag [QSA] (query string append) is not present, the query string of the original request gets replaced instead of appended. So the query string is gone after this rewriting.
This would be a lot easier if you wouldn't mess with the query string. The easiest way of rewriting any url that is not an existing file would be if the second line would be simply RewriteRule (.+) /index.cfm - you could then get all info about the current request, including query string, path and file, in the script.
So now you'd have to fiddle with the query string. Adding [QSA] will pass the query string to your script and you'd have to detect what's inside. This will work only if you do not expect the query string to contain parameters named "event" and "uri" - these will be overwritten by your rewriting. If you need to add the original query string to the URL, it's a bit more complicated, because the string needs to be url-encoded.
Here's how to do that.
Based on your comments, it sounds like you need to use the Query String Append QSA flag on your rule like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.cfm?event=checkuri&uri=$1 [QSA,L]
In your example case the rewrite would look like:
/index.cfm?event=checkuri&uri=index.php&id=123412
Sven was very close so I'm giving him the check
This ended up working perfectly:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} ^[A-Z]+\ ([^\s]+)
RewriteRule (.+) /index.cfm?event=checkuri&uri=%1 [QSA]
I am trying to get url from:
192.168.0.1/movie-page.php?id=123
to:
192.168.0.1/movie/movie-name
or even (for now):
192.168.0.1/movie/123
I've simplified it by using this url (to get something working):
192.168.0.1/pet_care_info_07_07_2008.php TO 192.168.0.1/pet-care/
my .htaccess file:
RewriteEngine On
RewriteRule ^pet-care/?$ pet_care_info_07_07_2008.php [NC,L]
What am I doing wrong? I've tried many combinations but no luck and my patience is running out...
I am running this on my local NAS which should have mod_rewrite enabled by default. I have tested .htaccess by entering random string in .htaccess file and opening the page, I got 404 error. I assume this means that .htaccess is being used since the page stops functioning if the file is malformed.
If you want to rewrite:
192.168.0.1/movie-page.php?id=123 too
192.168.0.1/movie/movie-name or 192.168.0.1/movie/123
Then you would do something like, but will require you manually add a rewrite for any new route (fancy url) you want, and eventually you may want your script to create routes dynamically or have a single entry point to sanitize:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^movie/([a-zA-Z0-9-]+)$ movie-page.php?id=$1 [L]
So a better method is to route everything through the rewrite:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
Then handle the route by splitting the $_GET['route'] with explode()
<?php
//192.168.0.1/movie/movie-name
$route = (isset($_GET['route'])?explode('/',$_GET['route']):null);
if(!empty($route)){
//example
$route[0]; //movie
$route[1]; //movie-name
}
?>
You want something like this:
RewriteRule ^movie/([0-9]*)$ /movie-page.php?id=$1 [L,R=301]
That will give the movie ID version with a numeric ID.
The main navigation of my site is coded like this:
<li>'.$value.'</li>'."\n";
But I would like the URL of the links to look like domain.co.nz/pagename, not domain.co.nz/index.php?pageId=pagename
How would you recommend I accomplish this?
Something like this should work:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?pageID=$1
First line turns on mod_rewrite. Second line sets the base URL to / (it's annoying, but you have to set it to the base path you're dealing with). Third and fourth lines make sure the request doesn't exist as a file, or as a directory. And the last line is the actual magic; basically it searches for "anything", captures what it finds in $1, and "rewrites" the URL to index.php?pageID=$1. If you learn to use regexes, you can do much more complicated things as well.
Yes, you can accomplish this with a .htaccess RewriteRule. In your .htaccess file, include:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) index.php?pageId=$1
This means:
If the REQUEST_FILENAME is not a valid file, redirect the entire URL to index.php?pageId=the entire URL
You'd then change your navigation to:
echo "<li>'.$value.'</li>'."\n";
Edit: I moved Trivikrtam's edit inline, see above. The RewriteRule should be index.php?pageId=$1 not /index.php?pageId=$1. Thanks #Trivikrtam!