Mefth Loader Gif
7 Minutes
Last Updated: 25-Jan-2022


How to Build your own BMI calculator using PHP, AJAX, and jQuery

BMI is a measure that anyone from 2 years old can use to see if he/she have a healthy weight for his/her height.

You may see a lot of web apps having this kind of calculator implemented in their web app but most of them works by refreshing the page after the user enters his/her height and weight.

But here will learn to do it:

  • Without refresh the page.
  • With having different background color for each result level.
  • With having different emojis for each result level.
  • With having different text color for each result level.
  • With having storing the results to database feature.
  • With having loading text while the user waiting the result feature.

Lets do our HTML code first

dynamic-bmi-calculator.html


<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>BMI calculator Built in with PHP, AJAX and jQuery</title>
	<link rel="stylesheet" type="text/css" href="style.css">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<h2>BMI calculator Built in with PHP, AJAX and jQuery</h2>
<form action="" id="check_bmi">
<label for="height">Your Height:</label>
<select id="height">
<option value="160">160 cm</option>
<option value="161">161 cm</option>
<option value="162">162 cm</option>
<option value="163">163 cm</option>
<option value="164">164 cm</option>
<option value="165">165 cm</option>
<option value="166">166 cm</option>
<option value="167">167 cm</option>
<option value="168">168 cm</option>
<option value="169">169 cm</option>
<option value="170">170 cm</option>
</select><br>
<label for="weight">Your Weight:</label>
<select id="weight">
<option value="60">60 Kg</option>
<option value="61">61 Kg</option>
<option value="62">62 Kg</option>
<option value="63">63 Kg</option>
<option value="64">64 Kg</option>
<option value="65">65 Kg</option>
<option value="66">66 Kg</option>
<option value="67">67 Kg</option>
<option value="68">68 Kg</option>
<option value="69">69 Kg</option>
<option value="70">70 Kg</option>
</select><br>
<div id="response-displayer"></div>
<input type="submit" name="submit" id="button" value="Check BMI">
</form>
</body>
</html>

I know you will leave this but its better to add our css code it make the page beautiful

style.css


body{
   margin: 0;
   padding: 0;
}
#check_bmi{
   padding: 5px 10px;
   border-radius: 5px;
}
#response-displayer{
   margin: 6px 5px 0;
   display: none;
   padding: 5px 8px;
   border-radius: 15px;
   box-shadow: 0 8px 16px 0 rgb(0 0 0 / 20%);
}
#check_bmi select{
    margin-bottom: 10px;
}
.response-message{
    padding: 16px;
    display: block;
    background-color: #fcc;
    color: red;
}

Now lets take a look at the jQuery code to send the details to PHP file to procceed the calculation and storing some data using ajax.

Before we implement any javaScript code don't remove this jquery CDN.


<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

or

You can use this jQuery CDN from Google.


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

As you want, just don't forget to add one of them to work with the below jQuery code.

script.js


<script>
$(document).ready(function(){ // WHEN PAGE IS READY
    // SEND HEIGHT AND WEIGHT USING AJAX
$("#check_bmi").on('submit', function(e){ // ON SUBMIT
    e.preventDefault(); // PREVENT DEFAULT BROWSER BEHAVOIR MEANS REFRESHING
    //PUT BOTH VALUES IN VARIABLE TO PASS TO PHP FILE PROCCESSOR
    var height = $("#height").val(),
        weight = $("#weight").val();
$.ajax({            // AJAX REQUEST
  type: 'POST',  // SENDING METHOD => POST
  url: 'bmi-calculator.php', // MAIN PHP PROCCESSOR PAGE
  data: {
     height: height,  // USER SELLECTED HEIHT
     weight:weight   // USER SELLECTED WEIGHT
    },
beforeSend: function() { // SHOW SOMETHING FOR USER WHILE WAITING THE RESULT
    $('#button').attr("value", "Wait..."); // CHANGE BUTTON TEXT TO Wait...
},
success: function(php_response) {          // PHP RESPONSE HANDLER
    $('#button').attr("value", "Check BMI");// CHANGE BUTTON TEXT TO Check BMI 
    $("#response-displayer").show(); // SHOW THE RESPONSE HANDLER ID
    $("#response-displayer").html(php_response).fadeIn(500);// DISPLAY RESULT
         }
       });
    });  
 });
</script>

You may got the idea of the above jQuery code

Now lets do the Backend code or the PHP proccessor file and MYSQL table to handle data and proccess it.

Here is the bmi_calculator table, why we need this? I will tell you later in this article.

  
CREATE TABLE `bmi_calculator` (
  `id` int(11) NOT NULL,
  `height` varchar(55) CHARACTER SET utf8 NOT NULL,
  `weight` varchar(50) CHARACTER SET utf8 NOT NULL,
  `score` varchar(55) CHARACTER SET utf8mb4 NOT NULL,
  `ip_address` varchar(50) NOT NULL,
  `time` timestamp(6) NOT NULL DEFAULT current_timestamp(6)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

ALTER TABLE `bmi_calculator`
  ADD PRIMARY KEY (`id`);
  

Now lets make MYSQL Database connection

db-connect.php

  
<?php
$database_host = "localhost";              
$database_user = "YOUR_DATABASE_USER";                   
$database_password = "YOUR_DATABASE_PASSWORD";                        
$database_name = "YOUR_DATABASE_NAME";
$db_conn = mysqli_connect($database_host, $database_user, $database_password, $database_name); 
if(!$db_conn){
echo "Sorry there is something wrong with our System, Please try again later!"; 
}
?>
  

bmi-calculator.php


<?php
if($_SERVER['REQUEST_METHOD'] === 'POST'){ // MUST BE POST REQUEST TO PREVENT DIRECT ENTERANCE TO THE PAGE BY WRITING OUR PHP FILE URL
include($_SERVER['DOCUMENT_ROOT'].'/db-connect.php'); // DB CONNCETION
$ip_address = $_SERVER["REMOTE_ADDR"]; // GET USER IP ADDRESS
$height = mysqli_real_escape_string($db_conn, $_POST['height']);  // HEIGHT
$weight = mysqli_real_escape_string($db_conn, $_POST['weight']); // WEIGHT

$count_all_used = $db_conn->query("SELECT id FROM bmi_calculator WHERE ip_address = '$ip_address' AND time > DATE_ADD(NOW(), INTERVAL -1 DAY)");
if($count_all_used->num_rows > 200){ // PREVENT MANY REQUESTS FROM THE SAME IP ADDRESS WITHIN 1 DAY
echo '<span class="response-message"> Sorry, We can\'t accept too many Requests to Measure within short period of time, Please try again after few hour.</span>';
}elseif(!in_array($height, range(160, 170))){// CHECK IF VALUE IS BETWEEN 160 AND 170
  echo '<span class="response-message"> Sorry, Something went wrong!</span>';// PROBABLY USER MODIFIED OUR FRONTEND SCRIPT    
}elseif(!in_array($weight, range(60, 70))){// CHECK IF VALUE IS BETWEEN 60 & 70
  echo '<span class="response-message"> Sorry, Something went wrong!</span>';// PROBABLY USER MODIFIED OUR FRONTEND SCRIPT     
}else{ // ALL VALUES ARE CORRECT SO LETS DO OUR CALCULATIONS
 $height_in_meter = $height / 100; // CONVERT CENTI-METER TO METER
// FORMULA OF BMI IS   BMI = KG/M SQUARE OR BMI = KG/MxM
 $total_height = $height_in_meter * $height_in_meter; // SO LETS MULTIPLY HEIGHT  VALUE BY ITS SELF
 $sub_total_bmi = $weight / $total_height; // NOW DIVID WEIGHT BY TOTAL HEIGHT
// TO PREVENT SOMTHING LIKE THIS 20.5428872... VALUE USE floor() FUNCTION TO THE REASULT CLEAR LIKE 20.5 SO NO MORE ANNOYING INFINITY DECIMAL NUMBERS
 $total_bmi = floor($sub_total_bmi * 10) / 10; 
 // STORE USER INFO ===========================================================>
 $insert_data_to_bmi_calculator = $db_conn->query("INSERT INTO bmi_calculator (height, weight, score, ip_address) VALUES ('$height cm', '$weight Kg', '$total_bmi', '$ip_address')");
 if(mysqli_fetch_array($insert_data_to_bmi_calculator) > 0) {
 // INFORM THE USER ===========================================================>
 if($total_bmi > 39.9){
  echo '<span class="response-message">🙄 Uhh! Your BMI Score is '.$total_bmi.'<br> Which means You\'re in  <strong>Obesity</strong> class III.</span>';      
 }elseif($total_bmi >= 35){
  echo '<span class="response-message">😏 Uhh! Your BMI Score is '.$total_bmi.'<br> Which means You\'re in  <strong>Obesity</strong> class II.</span>';      
 }elseif($total_bmi >= 30){
  echo '<span class="response-message">😕 Uhh! Your BMI Score is '.$total_bmi.'<br> Which means You\'re in  <strong>Obesity</strong> class I.</span>';     
 }else if($total_bmi >= 25){
  echo '<span class="response-message" style="background:gold;">😒 Uhh! Your BMI Score is '.$total_bmi.'<br> Which means You\'re <strong>Overweight</strong>.</span>';  
 }elseif($total_bmi <= 18.5){
  echo '<span class="response-message" style="background:gold;">😌 Uhh! Your BMI Score is '.$total_bmi.'<br> Which means You\'re <strong>Underweight</strong>.</span>';      
 }else{
  echo '<span class="response-message" style="color: green;background-color: lightgreen;">😊 Great! Your BMI Score is '.$total_bmi.'<br> Which means You\'re in <strong>Average</strong> weight.</span>';       
      }
}else{
  echo '<span class="response-message">Sorry, Somthing wrong happen, please try again later.</span>';      
     }      
   }    
}else{ 
    header( "HTTP/1.1 301 Moved Permanently" ); // REDIRECT HIM/HER BECAUSE THEY ARE TRYING TO ENTER TO OUR PHP PAGE DIRECTLY
    header("Location: https://www.mefth.com/web-dev-tutorial/build-bmi-using-php-ajax-and-jquery");
    exit(); 
}
?>

Lets see what is the above PHP code about

1st You should prevent direct enterance to your PHP code, This means Some developers try to enter to your PHP code directly just by writing its URL, So you should make sure the page should be accessible only on POST request, which is in our case it should be come from our AJAX request.
In every AJAX request there is a request Method header sent with the header of the http request, so we have to check that by $_SERVER['REQUEST_METHOD'] method and compare it with POST, so if that is TRUE then let our PHP script do the rest of the work.

2nd Get the IP Adress of the user, next get the user height and weight, Next you should use mysqli_real_escape_string Function to prevent most well known MYSQL injection attact. In our case just for best practice.

3rd You website may get a lot of Bots by just clicking your check button to weaken your server, Since there is no any validation and all the selected data are already entered. So to prevent such kind of probelem you should make some limitation per the user IP Address. To do that you should already stored the current user IP Address and check that IP Address if it makes more than the maxmimum request limit in our case one IP Address shouldn't has more than 200 requests per a day.

Whenever you decide to limit user per IP Address you should think that one IP Address could be used by many users that are in the same WIFI or network.
So let the limit a lot more. On therhand you should be take care of many Bots that are trying to weaken your SERVER.

If you're still reading the whole article up to this line, you're really want to learn, so let me explain in server side valiation of the user inputs (height and weight).

4th You must validate any user input even the values are coming from select option, Because any of our frontend code can be modified by exprienced developers so we've to accept a valid data only. In our case I've used in_array and range Fuctions to check if the value is not in the range of the given values.

The Formula of BMI is BMI = Weight divid by Height Square or BMI = W/H2 But in our case I've to convert the value of Height centimeter in to Meter. After we've divided the values, we may get some long number in decimal format, so to prevent such kind of number we've to wrap the numbers to only one nearest number. So to do this you've to use floor() function and times by 10 and out of braket times 10 so the value will be a clear number with having only one number after the decimal point.

5th Do you know why you have to store user data?

You have to store user data why? Because:

  • It can help you to know how many requests are your calculator has been recieved.
  • It can help you to let you know your users are a real humans or calculation is submited by Bots if you stored users device name or userAgent.
  • It can help you to make a request limit for every user. So no unlimited submision or calculations can happen to your server. That's way I've made this article using PHP for calculations.

Finally, just echoing out the result according to its value.

All Users are just copied the above code and has gone already, so you're the only one here continue reading the article, Here is Bonus for you...

In the first HTML select dropdown option there are small amount of number for example for height there are only from 160 cm to 170 cm, So what if user wants to select more than or less than these numbers?

I'm sure you will tell me just add extra numbers below and before each select option like this...

    
<option value="161">161 cm</option> <!-- BEFORE -->
<!---- OR ------>
<option value="171">171 cm</option> <!-- AFTER -->    
    

Right?

Well, you're right.

But It will be a lot of option tag for both height and weight in your HTML code, So to solve that you can use php for loop, here it is

   
<select id="height">
<?php
for($i = 80;$i <= 240;$i++){ // SO USER CAN SELLECT IN THE RANGE OF 80 TO 240 cm
    echo '<option value="'.$i.'">'.$i.' cm</option>';
}
?>
</select>
    

The same do like this for Weight also,

   
<select id="weight">
<?php
for($i = 10;$i <= 150;$i++){ // SO USER CAN SELLECT IN THE RANGE OF 10 TO 150 Kg
    echo '<option value="'.$i.'">'.$i.' Kg</option>';
}
?>
</select>
    

Now you will have all the option tag with its value in the given range. But if I were with you, you may ask me I want to write selected for one of those numbers.

For Height here it is

   
<select id="height">
<?php
for($i = 80;$i <= 240;$i++){
    if($i == 170){ // INSERT YOUR PREFERED HEIGHT TO BE BY DEFAULT SELLECTED NUMBER
    echo '<option value="'.$i.'" selected>'.$i.' cm</option>';   
    }else{
    echo '<option value="'.$i.'">'.$i.' cm</option>';
    }
}
?>
</select>
    

The same goes to Weight...

   
<select id="weight">
<?php
for($i = 10;$i <= 150;$i++){
    if($i == 70){ // INSERT YOUR PREFERED WEIGHT TO BE BY DEFAULT SELECTED NUMBER
    echo '<option value="'.$i.'" selected>'.$i.' Kg</option>';   
    }else{
    echo '<option value="'.$i.'">'.$i.' Kg</option>';
    }
}
?>
</select>
    

When PHP loops in the range of i value and arrives at the option tag value and the value is the same with the number in after comparision oparator then that option tag will be always the default value of the dropdown select option.

Now that's it from me.

If you're statsfied with this article you will probably share or comment below. If not or have a question Contact me directly.

Thank you 😊

URL Copied
Share this              

Report for Comment or Reply




Mefth Loader gif

Be the first to ... Write comment.

You must Login to write Comment.

SUBSCRIBE to newsletter To get the most updated contents through your Email.



We've Recommended Articles for you