Pregunta

Trying to learn about using functions in PHP: if I want start a variable at a value of 0, and use assignment-operators to add to it, how would I do that within a function? Kinda hard to describe in words, so, here's an example:

<?php
function tally($product){

  // I want these to be the starting values of these variables (except for $tax, which will remain constant)
  $tax = 0.08;
  $total_price = 0;
  $total_tax = 0;
  $total_shipping = 0;
  $grand_total = 0;

  // So, the program runs through the function:

  if($product == 'Candle Holder'){
    $price = 11.95;
    $shipping = 0;
    $total_price += $price;
    $total_tax += $tax * $price;
    $total_shipping += $shipping * $price;
    $grand_total = ($total_price + $total_tax + $total_shipping);
  }
  else if($product == 'Coffee Table'){
    $price = 99.50;
    $shipping = 0.10;
    $total_price += $price;
    $total_tax += $tax * $price;
    $total_shipping += $shipping * $price;
    $grand_total = ($total_price + $total_tax + $total_shipping);
  }
  else if($product == 'Floor Lamp'){
    $price = 44.99;
    $shipping = 0.10;
    $total_price += $price;
    $total_tax += $tax * $price;
    $total_shipping += $shipping * $price;
    $grand_total = ($total_price + $total_tax + $total_shipping);
  }else{
    echo '<li>Missing a product!</li>';
  }
  // And then, it echoes out each product and price:
  echo '<li>'.$product.': $'.$price;
  // To test it, I echo out the $grand_total to see if it's working:
  echo '<br>---'.$grand_total;
} //end of function tally()

// End of the function, but every time I call
tally('Candle Holder');
tally('Coffee Table');
tally('Floor Lamp');
?>

it doesn't add to the $grand_total of all three products. I know it's because the function runs through the beginning (top) and resets $grand_total to 0. If I try to place the original-value variables outside of the function, the browser returns an error: undefined variable.

I know this is jumbled, so tell me if I need to supply more info. Thanks!

EDIT


Found another way to simplify it. Totally had forgotten about the return function:

<B>Checkout</B><br>
Below is a summary of the products you wish to purchase, along with totals:
<?php

function tally($product, $price, $shipping){

$tax = 0.08;

    $total_tax = $tax * $price;
    $total_shipping = $shipping * $price;
    $grand_total = ($total_price + $total_tax + $total_shipping);

echo '<li>'.$product.': $'.$grand_total;
return $grand_total;

} //end of function tally()

?>
<ul>
<?php
    $after_tally = tally('Candle Holder', 11.95, 0);
    $after_tally += tally('Coffee Table', 99.50, 0.10);
    $after_tally += tally('Floor Lamp', 49.99, 0.10);

?>
</ul>
<hr>
<br>
<B>Total (including tax and shipping): $<? echo number_format($after_tally, 2); ?></B>

Does exactly what I wanted it to! Thanks for the help! I know that arrays could help with this, but I'm just now getting to that in my lessons.

¿Fue útil?

Solución

You need to be aware of scope. functions don't have access to standard variables unless you either pass them to the function or globalize them in the function. Ideally you pass what you need to the function.

In your case you're expecting a function - an isolated process - to work as a constantly running program... or something of the sort. Perhaps what you need to do is reconsider what you expect from tally($product)...

<?php
function tally($product)
{
    $tax = 0.08;
    $total_price = 0;
    $total_tax = 0;
    $total_shipping = 0;
    $grand_total = 0;

    if($product == 'Candle Holder'){
        $price = 11.95;
        $shipping = 0;
        $total_price += $price;
        $total_tax += $tax * $price;
        $total_shipping += $shipping * $price;
        $grand_total = ($total_price + $total_tax + $total_shipping);
    }
    else if($product == 'Coffee Table'){
        $price = 99.50;
        $shipping = 0.10;
        $total_price += $price;
        $total_tax += $tax * $price;
        $total_shipping += $shipping * $price;
        $grand_total = ($total_price + $total_tax + $total_shipping);
    }
    else if($product == 'Floor Lamp'){
        $price = 44.99;
        $shipping = 0.10;
        $total_price += $price;
        $total_tax += $tax * $price;
        $total_shipping += $shipping * $price;
        $grand_total = ($total_price + $total_tax + $total_shipping);
    }

    return $grand_total;
}

$grand_total = 0;
$grand_total += tally('Candle Holder');
$grand_total += tally('Floor Lamp');

?>
<ul>
    <li>Candle Holder: $<?php echo tally('Candle Holder'); ?></li>
    <li>Floor Lamp: $<?php echo tally('Floor Lamp'); ?></li>
    <li>Total: $<?php echo $grand_total; ?></li>
</ul>

In this example you can see I use $grand_total inside and outside the function. They are unrelated. The function does not know about the outside $grand_total because it is not within its scope.

This function is used for only one thing - tally the total for that product. It's up to you to compound the results for each product. You could write a function to tally all, or a class to handle it all, but that's another subject. This example just explains why it is not doing what you are asking for

Otros consejos

The problem as others have stated is scope. In your situation with the code you have, maybe use a static var (not preferred), pass true as second arg to reset $grand_total to 0:

function tally($product, $reset=false)
{
    //your vars
    static $grand_total = 0;

    if($reset) {
        $grand_total = 0;
    }

    //your code

    return $grand_total;
}

Better would be to just return the $grand_total and sum it in your code that calls the function.

However, I would consider using an object. At a minimum, add the products and prices into an array in a file that can be included and then loop over when needed:

$tax = 0.08;

$products = array(
    'Candle Holder' => array(
        'price' => 11.95,
        'shipping' => 0,
    ),
    'Coffee Table' => array(
        'price' => 99.50,
        'shipping' => .10,
    ),
);

$grand_total = 0;

foreach($products as $product => $values) {
    $total = $values['price'] + ($tax * $values['price']) + ($values['price'] * $values['shipping']);
    $grand_total += $total;
    echo '<li>'.$product.': $'.$values['price'];
}
<?php

$input_product_array = array("Candle Holder","Coffee Table");

function tally($incomingarray){

$tax = 0.08;
$total_price = 0;
$total_tax = 0;
$total_shipping = 0;
$grand_total = 0;

$return_product_array = array(); // we're doing this so we can return multiple product row entries and a single grand total it'll make sense shortly

foreach ($incomingarray as $key=>$productname) {

if($productname == 'Candle Holder'){
    $price = 11.95;
    $shipping = 0;
    $total_price += $price;
    $total_tax += $tax * $price;
    $total_shipping += $shipping * $price;
    $grand_total = ($total_price + $total_tax + $total_shipping);
    $return_product_array[] = '<li>'.$productname .': $'.$price.'</li>';
} else if($productname == 'Coffee Table'){
    $price = 99.50;
    $shipping = 0.10;
    $total_price += $price;
    $total_tax += $tax * $price;
    $total_shipping += $shipping * $price;
    $grand_total = ($total_price + $total_tax + $total_shipping);
    $return_product_array[] = '<li>'.$productname .': $'.$price.'</li>';
} else if($productname == 'Floor Lamp'){
    $price = 44.99;
    $shipping = 0.10;
    $total_price += $price;
    $total_tax += $tax * $price;
    $total_shipping += $shipping * $price;
    $grand_total = ($total_price + $total_tax + $total_shipping);
    $return_product_array[] = '<li>'.$productname .': $'.$price.'</li>';
} 

}
//now we construct a final return array which contains all of our products array in one entry and then the grandtotal/totalprice/totaltax/total shipping in other columns

$returnarray = array($return_product_array,$grand_total,$total_shipping,$total_tax,$total_price);

return $returnarray;

}


$returnedinfo = tally($input_product_array);

//now we can spit out our products
foreach ($returnedinfo[0] as $key=>$productlist) { // always going to be an array returned from function and element 0 will always be items
    echo $productlist;  
}


echo "totals<br />";
echo "Pre-Tax Total = $".$returnedinfo[4];
echo "Total Tax = $".$returnedinfo[3];
echo "Total Shipping = $".$returnedinfo[2];
echo "Grand Total = $".$returnedinfo[1];
?>

Something like this

This happens due to a programming concept called 'scope' While the function's code is run, the values are just what you want them to be.

In order to solve the problem, first of all declare the variables OUTSIDE the function.

<?php
$tax = 0.08;
$total_price = 0;
$total_tax = 0;
$total_shipping = 0;
$grand_total = 0;
tally('Candle Holder');
tally('Coffee Table');
tally('Floor Lamp');
?>

Then inside the function tally(), add this piece of code before your if/else statements

global $tax;
global $total_price;
global $total_tax;
global $total_shipping;
global $grand_total;

This pretty much tells the function that there is a variable called "tax" that is outside its current "scope", and that it should link it into its current memory. Then when the function updates the value of tax, it is updating the main variable outside of its "scope", hence preserving the values (I gave a example of tax, same for every other variable you declare global)

Ps: I understand i might of got your question wrong, if so do tell me and i will update the answer.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top