variables outside/inside of a function: PHP beginner - php

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.

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

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.

Related

WooCommerce new order email notification

In Woocommerce, I have created a custom cart with different calculated tax and new total.
How can I send the email with this new data?
In what file of Woocommerce?
<?php
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$product =wc_get_product( $values['data']->get_id());
echo "<b>".$product->get_title().'</b><br> Quantità: '.$values['quantity'].'<br>';
$price = get_post_meta($values['product_id'] , '_price', true);
echo "Prezzo: ".$price."<br>";
$carrello = $values['quantity'] * $price;
echo "Totale: ".$carrello."<br>";
// Below the new data with tax and discount calculation:
$percent = ($tax_amount / $without_tax) * 100;
if ($percent == "10")
$tax_rate = 10;
else $tax_rate= 4;
$with_tax = $scontato;
$totaleforsebene = ($scontato * $percent)/100;
$totalForSebeneArray[$values['data']->get_id()] = $totaleforsebene; // add the value by the item ID
$totaleforsebene = number_format($totaleforsebene, 2, '.', '')." €";
}
?>
<th>Iva<br />Totale chiusura</th>
<td>
<?php
$totaleiva_1 = 0;
$items = $woocommerce->cart->get_cart();
foreach($items as $item ) {
$totaleiva_1 += $totalForSebeneArray[$item ['data']->get_id()];
}
$totaleiva_1 = number_format($totaleiva_1, 2, '.', '');
echo "€"; echo $totaleiva_1;
echo "<br>";
$totalefinitocarrello = $totaleiva_1 + $total;
echo "€"; echo $totalefinitocarrello;
?></td></tr>
<?php endif; ?>

Cart Price Discount according to quantity value

How can i apply 5% discount in base price after Quantity cross 15 in custom e Commerce.
Code:
$price = $_POST['price'];
$quantity = $_POST['quantity'];
$discount = $_POST['discount'];
$tax = $_POST['tax'];
$shipping = $_POST['shipping'];
$payments = $_POST['payments'];
$total = (($price * $quantity) + $shipping) - $discount;
$price = mysqli_real_escape_string($conn , $_POST['price']);
$quantity =mysqli_real_escape_string($conn , $_POST['quantity']);
if ($quantity > 15)
{
$discount = ($price/100)*5;
$price = $price - $discount;
}
else
{
$price = $price;
}

How to specify shipping_cost regarding all products in session?

I got a problem with the following script, which is listing all products from a session. There are products with different $shipping_cost (0.7 or 6.99).
If I have in my card:
products with product_code<100 = shipping_cost should be 0.7,
products with product_code>100 = shipping_cost should be 6.99,
products with product_code<100 AND product_code>100 = shipping_cost keep 6.99.
<?php
if(isset($_SESSION["products"]) && count($_SESSION["products"])>0){
$total = 0;
$list_tax = '';
$gs = 0.70;
$cart_box = '<ul class="view-cart">';
foreach($_SESSION["products"] as $product){ //Print each item, quantity and price.
$product_name = $product["product_name"];
$product_qty = $product["product_qty"];
$product_price = $product["product_price"];
$product_code = $product["product_code"];
$item_price = ($product_price * $product_qty); // price x qty = total item price
$cart_box .= "<li class=\"view-cart-total\">$product_code – $product_name – Anzahl : $product_qty = <strong>" .number_format($item_price, 2, ",", "."). " ".$currency."</strong></li>";
$subtotal = ($product_price * $product_qty); //Multiply item quantity * price
$total = ($total + $subtotal); //Add up to total price
}
if($product_code < 100){
$shipping_cost = $gs;} //Gutschein-Versandkosten
elseif($product_code > 100){
$shipping_cost = $shipping_cost;} //Gutschein-Versandkosten
else {$shipping_cost = $shipping_cost;}
$grand_zw = number_format($total, 2, ",", "."); //Zwischensumme
$grand_total = $total + $shipping_cost; //Gesamtbetrag
foreach($taxes as $key => $value){ //list and calculate all taxes in array
$tax_amount = ($grand_total - ($grand_total / 119 * 100)); //MwSt
$tax_item[$key] = $tax_amount;
$grand_total = $grand_total + 0;
}
foreach($tax_item as $key => $value){ //taxes List
$list_tax .= $key. ' ' .number_format($value, 2, ",", "."). ' '.$currency. '<br />';
}
$grand_netto = ($grand_total - $tax_amount);
$shipping_cost = ($shipping_cost)?'Versandkosten = '. number_format($shipping_cost, 2, ",", ".").' '.$currency.'<br />':'';
//Print Shipping, VAT and Total
...
?>
Problem is, if I have both products (product_code<100 and product_code>100) in the card, it regards only the last product I've given to the card.
So $shipping_price is either 0.7 or 6.99.
You have to put the shipping cost logic inside the foreach loop, this would be a possibility:
$shipping_cost = 0.7;
$total_products_number = 0;
foreach($_SESSION["products"] as $product) {
... here is your existing code of the foreach loop
if($product_code > 100) {
$shipping_cost = 6.99;
}
$total_products_number += $product["product_qty"];
}
if($total_products_number>1) {
$shipping_cost = 6.99;
}
That way the default shipping costs are 0.7 and are only changed to 6.99 if there is a product with $product_code > 100 or if there is more than one product in quantity.

Why isn't working my notifications script with sales module?

The sales notifications is not working because this line amountArray[$idproduct] += $amount; is returning me offset. I don't know how to fix it.
My full function is this:
function saveAllSaleDetails($idsale, $sale) {
$this->conexion->startTransaction();
$amountArray = [];
try {
foreach ($sale as $detail):
$idproduct = $detail['id'];
$amount = $detail['amount'];
$price = $detail['price'];
$subtotal = $detail['subtotal'];
$iduser = 1;
$this->saveSaleDetail($idsale, $idproduct, $amount, $price, $subtotal, $iduser);
$amountArray[$idproduct] += $amount;
$stock = $this->product->getProductStock($idproduct);
$stock = $stock[0][0] - $amountArray[$idproduct];
if ($stock <= 20) {
$product = $this->product->getProductById($idproduct);
$message = $product[0][1]." stock is bellow 20.";
notification::add($message, $idproduct, 'warning', 'product.php');
}
endforeach;
$this->conexion->commit();
$this->conexion->cerrar();
return true;
} catch (Exception $e) {
$this->conexion->rollback();
$this->conexion->cerrar();
var_dump($e->getMessage());
return false;
}
}
The problem is because of this line,
$amountArray[$idproduct] += $amount;
The above statement can be expanded as
$amountArray[$idproduct] = $amountArray[$idproduct] + $amount;
Initially during the first iteration of foreach loop, $amountArray[1] and $amountArray[2] are not set, and hence you're getting these undefined offset error.
So instead of
$amountArray[$idproduct] += $amount;
Do this:
$amountArray[$idproduct] = isset($amountArray[$idproduct]) ? $amountArray[$idproduct] + $amount : $amount;

How to add values in php?

I thought I had this syntax right, but apparently I don't... here's what I have.
/* Price Calculation */
if ($stage="1") $price + 1000 = $price;
if ($stage="2") $price + 2500 = $price;
if ($stage="3") $price + 5000 = $price;
if ($chrome=on) $price + 100 = $price;
if ($bov=on) $price + 200 = $price;
if ($controller=on) $price + 500 = $price;
if ($filter=on) $price + 50 = $price;
print "<br /><u>Total: </u>";
echo $price;
The variables are already declared correctly, so I know it isn't that. The php has a problem with the ='s. What did I do wrong?
you should use == in condition
if ($stage="1")
should be
if ($stage=="1")
and adding should be
$price = $price + 1000;
Your code should be
<?php
/* Price Calculation */
if ($stage=="1") {
$price = $price + 1000;
}
if ($stage=="2") {
$price = $price + 2500;
}
if ($stage=="3") {
$price = $price + 5000;
}
if ($chrome==true) {
$price = $price + 100;
}
if ($bov==true) {
$price = $price + 200;
}
if ($controller==true) {
$price = $price + 500;
}
if ($filter==true) {
$price = $price + 50;
}
echo "<br /><u>Total: </u>";
echo $price;
?>
I don't know why you are using on. I think, it's a Boolean condition.
if ($stage=="1") $price = $price + 1000;
if ($stage=="2") $price = $price + 2500;
if ($stage=="3") $price = $price + 5000;
if ($chrome==on) $price = $price + 100;
if ($bov==on) $price = $price + 200;
if ($controller==on) $price = $price + 500;
if ($filter==on) $price = $price + 50;
print "<br /><u>Total: </u>";
echo $price;
Shouldn't it be $price = $price + 100; or $price += 100?
Also, you are mistaking your assignment for equality testing. = never meant equality in php---it means assignment (think of it $price = $price + 100 doesn't make sense it it is equality). To test for equality, use == (check your conditions).
You should change your code to:
if ($stage=="1")
$price = $price + 1000;
if ($stage=="2")
$price = $price + 2500;
if ($stage=="3")
$price = $price + 5000;
if ($chrome==on)
$price = $price + 100;
if ($bov==on)
$price = $price + 200;
if ($controller==on)
$price = $price + 500;
if ($filter==on)
$price = $price + 50;
print "<br /><u>Total: </u>";
echo $price;
Hope this helps :)
In addition to using == for comparison (since = is for assignment), consider adding using the += operator to add values to variables. Also, while it works, many folks consider it bad practice to skip your curly braces.
if ($stage=="1") {
$price += 1000;
}
...
if ($stage=="1") $price += 1000;
if ($stage=="2") $price += 2500;
if ($stage=="3") $price += 5000;
if ($chrome=="on") $price += 100; // if your want to use "on" instead of TRUE, use it as a string
if ($bov=="on") $price += 200;
if ($controller=="on") $price += 500;
if ($filter=="on") $price += 50;
echo "<br /><u>Total: </u>";
echo $price;
There are a couple of problems:
(1)
You are trying to assign the value of $price into $price + number, which is impossible. Try:
$price = $price + number;
(2)
Use the == operator for checking equality, like:
if ($stage == "1")
A single = is the assignment operator.

Categories