Mod rewrite rule to append query string and continue - php

Not sure if there's a reasonable way to do this or if maybe I'm missing something. I have a content management system that I've build that passes everything through a template system (which is essentially a single PHP file that does the processing). With that in mind, the following rules will send requests to lucy.php where the url is validated and the appropriate template loaded.
RewriteRule ^$ lucy.php [L,QSA]
RewriteRule ^([^/\.]+)/?$ lucy.php?section1=$1 [L,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ lucy.php?section1=$1&section2=$2 [L,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ lucy.php?section1=$1&section2=$2&section3=$3 [L,QSA]
So each part of the URL is sent as a section# variable to the script. My issue is when I'm using a template that requires its own URL system. In this case... a blog. Normally, I would do something like
RewriteRule ^blog/([0-9]{4})/([0-9]{2})/([0-9]{2})/([^/\.]+)/?$ site/blog.php?year=$1&month=$2&day=$3&blog_url=$4 [L,QSA]
to send the request to a one off script. The way I'm doing it now is that http://domain.com/blog will still go through the aforementioned lucy.php script where a blog template is loaded and displayed. So, is it possible to continue allowing the /blog portion of the request to be routed to the appropriate rewrite rule but to also append the year, month, day, and blog_url fields to the query string? The /blog url will not consistently be the same and may not even be called blog, so I need something that will work dynamically.
The only idea I had was to duplicate each instance of the lucy.php rewrites to include optional parameters for date based structures. Something like...
RewriteRule ^([^/\.]+)/([0-9]{4})/([0-9]{2})/([0-9]{2})/([^/\.]+)/?$ lucy.php?section1=$1&year=$2&month=$3&day=$4&item_url=$5 [L,QSA]
But I thought there might be more efficient way of doing it. The other issue with that convention is that I'd like this to work for other scenarios like category, author, and other non-blog scenarios. I don't want to have to duplicate the block of lucy.php rewrites for every one of these instances. Thoughts?

Pass the complete URL and then Parse it in PHP instead of writing out new rules
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /lucy.php?url=$1 [QSA,L]
Edit:
In PHP I use this ...
function parseUrl(){
$tempArray = explode('/', $_GET['url']);
foreach($tempArray as $section){
if(stristr($section,':')){
$tempParamArray = explode(':',$section);
if(stristr($tempParamArray[1],',')){
$tempParamArray[1] = explode(',',$tempParamArray[1]);
}
$this->parameters[$tempParamArray[0]] = $tempParamArray[1];
}else{
if(!empty($section)){
array_push($this->sections,$section);
}
}
}
}
I then use URLS like ...
/section1/section2/section3/
/blog/date:01-01-2013/

Related

.htaccess URL rewrite with random parameters

I'm currently writing a PHP app and am about to create various controllers. Currently I have one controller with certain method, so the URL looks like this:
http://somewebsite.com/index.php?c=controller&a=action
It's being rewritten to this:
http://somewebsite.com/controller/action
With this .htaccess file:
RewriteEngine On
RewriteRule ^([a-z]+)/([a-z]+)$ index.php?c=$1&a=$2 [NC]
What I want to achieve is the ability to rewrite URL with more than one controller (the more, the better), possibly in random order. Is there a more convenient way than rewriting every possible combination of URL parameters?
Many frameworks (Codeigniter, WordPress, Laravel, etc.) use an .htaccess file similar to the following:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
This rewrites all incoming URLs to be handled by the index.php file. You can then use $_SERVER['REQUEST_URI'] variable to get the exact request URI, parse it, and then handle it how you want.
if you're going for an arbitrary routing scheme, probably your best bet is to just pass the entire url string e.g. ^(.+)$ to index.php and let your php application split the string based on '/' and handle the array however makes sense for your application

How to implement mod_rewrite after PHP redirection?

I have a lot of old urls I need to redirect to certain categories.
www.example.com/some-requested-product -> www.example.com/index.php?categories=some-requested-product
www.example.com/some-requested-article -> www.example.com/index.php?articles=some-requested-article
www.example.com/some-requested-user -> www.example.com/index.php?users=some-requested-user
And so on - I hope you get the point. (Actually there's no hint in the URL about the content type.)
I've created a redirection, now I can reach the content I need:
RewriteRule ^([a-zA-Z0-9-]+)$ /index.php%{REQUEST_URI}
In the PHP I can query now the urls to see what type of content it is:
if ($_SERVER['REQUEST_URI'] == "/some-requested-content") { Redirect($BaseURL."/index.php?category_type=some-requested-content", false); }
Redirection is made, content is fetched. (I know it's not safe etc. just for testing.)
My main problem is now, how can I mask the URL after these events?
I would like to see the same URL originally requested ( www.example.com/some-requested-content ) in the address bar of the browser, not the one it is redirected to.
Is it possible?
Or can you think about another solution?
You're looking for query string append (QSA)
RewriteCond %{REQUEST_URI} ^/some-requested-article$
RewriteRule ^(.*)$ index.php?articles=$1 [L,QSA]
RewriteCond %{REQUEST_URI} ^/some-requested-product
RewriteRule ^(.*)$ index.php?categories=$1 [L,QSA]
and so on, you'd make the regex cover each case of query string, like category, articles, users, and so on.
The L means last to process in the rewrite rules, that's very important to use.
This preserves the visible URI, but internally passes the page processing the request the desired query string data.
So you aren't really 'masking' the url, the url is basically simply filling in the desired query string data, which is then sent to the file processing the request. This is a common method, it's how a lot of blogging and cms platforms handle search engine friendly urls, for example.
Note however that because you didn't provide a more accurate example of your real urls in each case, the solution I am posting would require regex that handles the variable values. If there is no actual pattern difference between the types, then you can't use this method, you'd have to go down the list of exact values/urls per query string type and list them as possible matches using the [OR] option in the RewriteCond tests. That works as long as there aren't too many pages involved.
Like so:
RewriteCond %{REQUEST_URI} ^/beans-are-fun$ [OR]
RewriteCond %{REQUEST_URI} ^/rice-is-fun$ [OR]
RewriteCond %{REQUEST_URI} ^/fun-with-rice-and-beans$
RewriteRule ^(.*)$ index.php?articles=$1 [L,QSA]

Handle .htaccess redirects with different parameters?

I would like to redirect urls that don't go into directories to one script (script1.php for example), and urls that have categories to another script (script2.php). Basically I would like to do something like this:
http://www.test.com/user1 -> http://www.test.com/script1.php?username=user1 where script1.php gets the username and presents an appropriate page for that user. I have that part working with this code:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ script1.php?username=$1 [L,QSA]
The problem now is that I would also like to have descriptive product urls so that for example http://www.test.com/clothes/jackets/cool-red-jacket-25 redirects to http://www.test.com/items.php?category=clothes&subcategory=jackets&id=25. I have some code that should work for that too:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([a-zA-Z-]+)/([a-zA-Z-]+)/.*-A([0-9-.]+)\.php$
script2.php?category=$1&subcategory=$2&id=$3 [L]
The problem I'm having is combining these 2 types of redirection. The first redirect always redirects to its own page and the second redirect will never get reached. Is it possible to combine these 2 and in which way? Basically I need something like this for htaccess if possible
if(!urlHasDirectories) {
redirect to script1.php?username=$username;
} else {
redirect to script2.php?category=$category&subcategory=subcategory&id=$id;
}
Lets go over basic regexs, we'll use Regex101 for this. The . is any character and * is a quantifier of the previous character/grouping zero or more times. So your first regex, RewriteRule ^(.*)$ script1.php?username=$1 [L,QSA] says rewrite anything that starts with anything and ends with anything to scripts1.php. That isn't what you want.
Demo: https://regex101.com/r/hK0xY3/1
With regexs it is best to be as specific as possible.
I would make your rule for users:
RewriteRule ^(user\d+)$ script1.php?username=$1 [L,QSA]
Demo: https://regex101.com/r/hK0xY3/4
The + is another quantifier here meaning one or more, so you could change that to an * if a number ins't required.
You said you wanted a regex that finds if there is a / in the path. I think it is best to tell the regex what to look at but that is possible:
^.+?\/
Demo: https://regex101.com/r/hK0xY3/3
With this approach though any directory request will be redirected...
for seo friendly url use this like :
RewriteRule ^user/([a-zA-Z0-9_-]+)$ user.php?username=$1
RewriteRule ^item/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ items.php?category=$1&subcategory=$2&id=$3
You need to put the more specific rule higher in the .htaccess file so it could be matched first. Use this in general.
Be awere that the most general rule (.*) that matches the rest of requests can be used for more different actions.
.com/john-doe // for user profile
.com/my-new-article // for showing article and so on
If you want to combine all those variations u need to decide which action to use (profile or showing article) on your application level. For example controller in mvc architecture. It can be accomplished easily by conditions.
if(userExists($userName))
// showing template for user profile etc...

Guidance on URL rewrite and construction

I am about to attempt writing of a photo sharing script and a script/rewrite that transforms numbers into descriptive names. I have a vague idea on how to go about doing this, so I was looking for some general comments/guidance.
Issue 1: I need to have a URL source for a photo which is stored above my root directory. I plan on appending the photo name (which is stored in my database) to my url as a query string, such as: www.mywebsite.com/getphoto.php?12_3.jpg and then writing a php script (getphoto.php) which takes the portion after the '?' and gets that photo from above the root.
Does this make sense and would there be any things to consider?
Issue 2: I want to transform a number at the end of my URL to a descriptive name (ie typing in facebook.com/4 displays facebook.com/zuck). I am not really sure the best way to go about doing this and was hoping for some guidance to get going in the right direction.
Thanks!
For Issue 1: a simple rewrite can handle that, you need to use the [QSA] flag. Something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^.*\.(jpeg|jpg|gif|png|bmp)$
RewriteRule ^(.+)$ /getphoto.php?photo=$1 [L,QSA]
This will rewrite behind the scenes the url http://mywebsite.com/12_3.jpg to http://mywebsite.com/getphoto.php?photo=12_3.jpg Note that the 3rd rewrite condition wants the URI to end with an image extension, you may not need it.
For Issue 2, it depends on how something like "4" maps to "zuck". If you are going to hardcode them into your apache config, you can use a RewriteCond:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/4$
RewriteRule ^.*$ /zuck [L]
RewriteCond %{REQUEST_URI} ^/5$
RewriteRule ^.*$ /mark [L]
etc. (or replace [L] with [R,L] to redirect instead of rewrite, or alternatively just use Redirect)
Redirect /4 /zuck
Redirect /5 /mark
etc.
If the mapping is stored in a database, your going to need to do this dynamically, perhaps as a php script to do a redirect, utilizing something similar to Issue 1. The rewrite rule would rewrite to something like /redirect.php?id=$1 and your redirect.php script would take the id and do a database lookup to see where to redirect the browser.

.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