Handle .htaccess redirects with different parameters? - php

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...

Related

RewriteRule different pages per user

I am deciding to create separate profile links for each user who registers on the website. I am using the .htaccess file RewriteRule to achieve this. The url I want to achieve should look something like www.domain.com/username. (I don't want www.domain.com/users/username)
Now the problem is, if I add a rule like RewriteRule ^(.*)$ /users.php?username=$1
it will matchup all URL addresses for www.domain.com, which may direct to any path. Even if I would like to visit www.domain.com/about page, it will be redirected to
www.domain.com/users.php?username=about, which I don't want. (Even if the requests was www.domain.com/products/abc)
I could apply filters in my users.php to filter such usernames, or if a username is not found in database, redirect to the page, but this means I have to change filters every time I decide to add a new page in my directory (in this case, any). Also, all traffic will be directed through 1 page, which may cause a performance problem.
Please suggest a way to achieve this, as There are websites that work like this. A possible RewriteRule or PHP code to achieve this.
You can use this rule in your root .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(\w+)/?$ /users.php?username=$1 [L,QSA]
I always use just simple rewrite as below:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)(.*)/?$ index.php
All traffic is redirected to index.php and using php I can run specific controllers depending on url. You should also think about. Almost all frameworks use such rule.
Then in your PHP file you should examine
$_SERVER['REQUEST_URI']
variable to route request to specific controllers

How to create Clean URL for every page using .Htaccess?

I'm currently in the progress of creating a huge website, but instead of the regular URLs I'd like to use Clean / User Friendly URLs. I have been searching on how could I basically tailor these Apache Mod Rewrite rules for my needs, howere I could not found any solution for my particular problem.
Below you can read the aim, which I'd like to achieve with the URLs (I'm not going to write the domain name each time, just imagine: http://www.example.com ahead of the URL parts).
/register/ OR /register ---> /register.php (It should support both of the variations.)
I actually have more files for the registration and I'd like them to be accessible using the "part" words like:
/register/part1/ OR /register/part1 ---> /register.php?part=1 (It should support both of the variations.)
Also, what if I have more than just one query varialbe? (Like "personal=1")
/register/part1/personal/ OR /register/part1/personal ---> /register.php?part=1&personal=1
And what if I have many more of these queries, but I CAN'T specify all of them before? Any of these can be entered. (Like "thing,name,job,etc")
/register/part1/personal/Nicky/ OR /register/part1/personal/Nicky ---> /register.php?part=1&personal=1&name=Nicky
OR any kind of variations you can imagine:
/register/part1/personal/thing/employee/ OR /register/part1/personal/thing/employee ---> /register.php?part=1&personal=1&thing=1&job=employee
EDIT:
This is what I've tried yet, but it just redirects the pages to index.php :/
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
So I have given you a lot of examples, what I'd like to basically achieve. I can have a lot of other pages besides "register.php" so it shouldn't be specific to that page only. I also want that which is VERY important, that IF someone goes to for example: register.php?part=1 it should redirect them to the appropriate Clean URL (of course in PHP).
I would also want to ask what should I do in the PHP end to make everything good? I saw that Wordpress has a really great solution for this, which is pretty automatic, and it looks great!
Is there any ways that someone could please explain me how to create a great .HTACCESS mod_rewrite solution for this? I would be really-really glad!
Please do not mark this question as duplicate, because I really did not found anything specific for my case.
You mentioned WordPress, which has something like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
What this does is redirect any request that doesn't match a real file or directory to the index.php script. That script will then decide what page to display. It will do so by looking into $_SERVER['REQUEST_URI'] which holds a path like register/part1.
It would be easier for you to figure out what page to show using this method, because in PHP there are many ways to parse that path string, then map it to a function
You should be able to construct clean URLs like this from your htaccess:
RewriteEngine On
RewriteRule ^index\.html$ /index.php?pageID=Home [L]
RewriteRule ^about-my-homepage\.html$ /index.php?pageID=About [L]
RewriteRule ^contact-us\.html$ /index.php?pageID=Contact [L]
the first is the one you want to output (the "clean" URL), the second one the one you actually want to open. Good Luck!

Mod rewrite rule to append query string and continue

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/

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.

Mod rewrite user URL

I'm lost here. I'm using this script to give users the opportunity to enter their username lijke this:domain/username
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ userpage.php?user=$1 [NC,L]
</IfModule>
This works fine. However, every user has pages I must link to: Video, Music, Images etc...
So I need something like:
domain/username/video
In php code it must be something like:
user.php?user=test&page=video
And one other question: What is the preferable way to link in this situation?
userpage.php?user=test&page=video
or
/test/video
And finally: Is it possible to deny the possibility to enter the url:
domain/userpage.php?user=test&page=video? Instead just always show: domain/test/video
Thanks in advance
I'm not 100% sure what you're asking? Do you need to change the rewrite rule to match the URL site.com/moonwalker/videos? You could try this:
RewriteRule ^([^/]+)/(images|videos|music)/?$ userpage.php?user=$1&page=$2 [NC,L]
Update
Just a quick note on the domain/member/videos URL structure. That could end up causing you problems in the future. For instance what if you decide to have a single page that shows all member videos? You'd probably want to URL to look something like site.com/members/videos. That's a problem, because the rewrite rule will also match that, but "members" isn't a member username.
I would probably structure my member page URLs like site.com/user/moonwalker/videos so it doesn't clash with future rewrite rules. You would change the above rewrite rule to this:
RewriteRule ^user/([^/]+)/(images|videos|music)/?$ userpage.php?user=$1&page=$2 [NC,L]
Then later on you can add a rewrite rule like:
RewriteRule ^members/(images|videos|music)/?$ allusers.php?page=$1 [NC,L]
To show all member videos.
Yes, it is possible by looking at the request line:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /userpage\.php[?\ ]
RewriteRule ^userpage\.php$ - [F]
This is necessary as the URL path could already be rewritten by another rule and thus using just RewriteRule would match those already rewritten requests too.

Categories