0

I have searched but could not get solution on this issue.

I am working on an application which will generate unknown number of items and have users select the quantity from a drop down against each item. Eg.

Item(s) | price | Select qty
Rice     23      3
Beans    22      4
Eggs     52      5

...
...
...
unknown

Please, how can I capture the above in an array and also calculate the total value for all selected items and corresponding fees?

I have the following HTML code:

<form id='form1' name='form1' method='post' action='item_calc.php'>
<?php
    .....
while($t_row = mysql_fetch_assoc($get_items)) {

echo "<p><label>$t_row['$item_name']
<input type='text' READONLY name='item_price[]' value='$t_row['$item_price']' /></label>
<input type='text' READONLY name='item_fees[]' value='$t_row['$item_fee']' /> 
<select name="item_qty">
<option value="1">
<option value="2">
<option value="3">
<option value="4">
<option value="5">
</select>
</p><p>";

}

        echo "<label><input type='submit' name='submit'  value='Submit' /></label></p>
         </form>";

Please, how can I get item_price[] + item_fees[] * item_qty for all selected items?

This is what I have tried:

for ($i = 0; $i < count($_POST['item_price']); $i++) {
   // Do something here with $_POST['checkbx'][$i]



   foreach ($_POST['item_fees'] as $tkey => $tvalue) {
    //echo "Key: $tkey; Value: $tvalue<br>";
   }


   foreach ($_POST['item_price'] as $pkey => $pvalue) {
    //echo "Key: $pkey; Value: $pvalue<br>";
   }

   $total = $tvalue + $pvalue;


}
echo $total;
hakre
  • 193,403
  • 52
  • 435
  • 836
Frank Nwoko
  • 3,816
  • 5
  • 24
  • 33
  • 1
    whatever you do, [make sure quantity is not a floating point value](http://stackoverflow.com/a/1470625/473637). – Jeshurun May 24 '12 at 22:03
  • Yes. Will keep that in mind. Any help? please. – Frank Nwoko May 24 '12 at 22:13
  • Not unknown but variable I think. So you could get the values of `item_price`, see as well [`array_values`](http://php.net/array_values). – hakre May 28 '12 at 11:12
  • Do you NEED to expose the price / fees to the html (for javascript?)? Or can you simply expose a product id instead and look up the product on submit and use the price & fee from that request instead? :-/ – sg3s Jun 01 '12 at 19:19

4 Answers4

2

I recommend to not put fees and prices into the form and read it out off the POST request. Some people do bad stuff like html injections or post parameter manipulation. You make them able to send you a request with their own prices and fees using manipulated POST parameters.

Simplest way to do this is to open your page with firefox and use firebug to manipulate the values of price[] and fees[] and then press submit - even if the inputs are readonly!!!

my tip - do something like:

<select name="quantity[unique-id]">
  <option value="null">choose...</option>
  ...your options...
</select>

where unique-id is the unique identifier of each product, like the database id.

And then in php

foreach ($_POST['quantity'] as $uniqueId => $quantity) {
  //... don't forget to check $uniqueId and $quantity for injections (like sql injections)
  //skip the products with no numeric quantity value
  if (!is_int($quantity) || $quantity < 1) {
    continue;
  }
  $fee = getFeeFor($uniqueId); // from database?
  $price = getPriceFor($uniqueId); // from database?
  //... do what you want: $price + $fee * $quantity
}

I hope this will help you.

Del Pedro
  • 1,216
  • 12
  • 32
  • Thanks Pedro. This looks solid. please how can I print all selected items and their respective prices and fees and also grand total? That is if the user selects 2 of n(item), I will print 2 * n(items) because I would like to store each item in units. As in treat 2 quantities as individual items. See http://stackoverflow.com/questions/10762618/mysql-database-design-structure I would like to use option 2 – Frank Nwoko May 26 '12 at 23:19
  • Pedro I did print_r ($uniqueId) but it's showing a blank page. – Frank Nwoko May 30 '12 at 11:30
  • I used your example as above but the page is showing blank. Try the example you gave and see. – Frank Nwoko May 31 '12 at 20:43
1
  1. First of all, don't include single quotes in a double quote string when you're referencing arrays, you risk to have an "encapsed string" error.
  2. You also include a double quoted string in "item_qty" which will likely result in an error.
  3. Close the option tags with /> as best practice.
  4. Your LABEL tag is not used properly. The correct syntax is: <label for='html_element_id'>My pretty label</label> <input id='html_element_id ... (my form control) ... /> and it's pretty useless (though always more semantic and structured) with other controls than checkboxes or radios.
  5. You may cosider using a TABLE instead of P tags to have everything lined up. Better, you could use CSS to line up things, much better practice.
  6. If you hard-code the choices it can be difficult to handle requirement changes: what if you need quantities from 1 to 10? What if you choose to use a textbox instead of a SELECT?

    while($t_row = mysql_fetch_assoc($get_items)) 
    {
        // Generate quantity string - can change the $qty string
        // for any imput method you like
    
        $qtyName = "item_qty[]";
    
        $qty = "<select name='" . $qtyName . "'>";
        for ($i=1; $i<6; $i++)
        {
            // close the option tag as best practice!
            $qty .= "<option value='" . $i . "' />";
        }
        $qty .= "</select>";
    
        echo sprintf("<p>%s
        <input type='text' READONLY name='item_price[]' value='%s' /></label>
        <input type='text' READONLY name='item_fees[]' value='$s' /> " . $qty . "</p>",
        $t_row['item_price'],
        $t_tow['item_fee']);
    }
    

Collecting the data would be simple:

$sum = 0;
$fees = $_POST['item_fee'];
$qtys = $_POST['item_qty'];
$prices = $_POST['item_price'];
$total = count($prices);

for ($i = 0; $i<total; $i++)
{
    $item_fee = $fees[$i] + 0; // trick to filter only numerical values and avoid data tampering
    $item_price = $price[$i] + 0;
    $item_quantity = $qtys[$i] + 0;

    $item_total = $item_price + $item_fee * $item_quantity; 

    $sum += $item_total;

}

I too agree that having a direct representation of prices in you form can lead anyway to data tampering, the user that suggested you to check against a database has given a very wise advice.

Cranio
  • 9,647
  • 4
  • 35
  • 55
  • 1
    "Close the option tags with /> as best practice." It really depends on the doctype. XHTML requires />. HTML 4 doesn't allow it. HTML 5 allows it, as optional. – oxygen May 29 '12 at 11:19
  • You're right, but you might agree with me that following the XHTML requirements, even if not mandatory, leads to more readable and debuggable HTML (expecially in large pages, complex layouts). That's why I've suggested a "best practice", by the way, and not "you _must_". This said, your observation is 100% correct and useful to stress :) – Cranio May 29 '12 at 13:26
0
$total = 0;
$fee = $_POST['item_fee'];
$qty = $_POST['item_qty'];

foreach($_POST['item_price'] as $k => $price) {
    $total += $price + ($fee[$k] * $qty[$k];
}

Don't sure if you want total of all itens, or total of each item.

If want total for each item, change $total += $price + ($fee[$k] * $qty[$k]; to $total = $price + ($fee[$k] * $qty[$k]; and remove the first line ($total = 0;).

Change <select name="item_qty"> to <select name="item_qty[]">

Gabriel Santos
  • 4,934
  • 2
  • 43
  • 74
0

I have a VERY SIMPLE solution.

First change <select name="item_qty"> to <select name="item_qty[]">

Then in your item_calc.php, write this

$itemprice = $_POST["item_price"];//tested with array(10,35,21)
$itemfees = $_POST["item_fees"];//tested with array(3,7,4)
$itemqty = $_POST["item_qty"];//tested with array(2,5,3)
$i = 0;
$total = 0;
foreach($itemprice as $price){
  $feesx = $itemfees[$i];
  $qtyx = $itemqty[$i];
  $calculated = ($price+$feesx)*$qtyx;
  $total = $total + $calculated;
  $i++;
}
echo $total;//echos 311 [{(10+3)*2}+{(37+7)*5}+{(21+4)*3}]

I tested it and is working perfect. Hope this helps :)

Alfred
  • 21,058
  • 61
  • 167
  • 249