Reputation: 69
I am building an order food online website. So basically, each item will has two sizes PT
and QT
with different price. I am able to add to cart if one of those two prices selected. But there is an issue, for example, if I selected PT
size and already added to cart, but if I want to change to QT
size later, it couldn't do that. I am not sure where is the bug at. Please take a look at my code and help me figure out this issue. Thank you.
DB (table name is items):
________________________________________________________________________________________________________________
id | product_code | product_name | product_desc | product_img_name | price | priceBig | product_type
-------+--------------+--------------------+--------------+------------------+-------+----------+---------------
1 | HS02 | Chicken Fried Rice | | 2.png | 5.50 | 7.50 | house_specials
index.php
$results = $mysqli->query("SELECT * FROM items WHERE product_type='house_specials' ORDER BY id ASC");
if ($results) {
while($obj = $results->fetch_object()) {
echo '<div class="product">';
echo '<form method="post" action="cart_update.php">';
echo '<div class="product-content"><h3>'.$obj->product_name.'</h3>';
echo '<div class="product-desc">'.$obj->product_desc.'</div>';
echo '<div class="product-info">';
echo 'PT '.$currency.$obj->price.'<input id="pt" type="radio" name="productSize" value="'.$obj->price.'" checked="checked" />';
echo 'QT '.$currency.$obj->priceBig.'<input id="qt" class="size_butt" type="radio" name="productSize" value="'.$obj->priceBig.'"/>';
// echo 'Price '.$currency.$obj->price.' | ';
echo 'Qty <input class="qtyBox" type="number" min="0" name="product_qty" value="1" size="3" min="0" />';
echo '<button class="add_to_cart">Add To Cart</button>';
echo '</div></div>';
echo '<input type="hidden" name="product_code" value="'.$obj->product_code.'" />';
echo '<input type="hidden" name="type" value="add" />';
echo '<input type="hidden" name="return_url" value="'.$current_url.'" />';
echo '</form>';
echo '</div>';
}
}
<h2>Your Cart</h2>
<?php
if(isset($_SESSION["items"]))
{
$total = 0;
echo '<ol>';
if (isset($_SESSION["items"])) {
foreach ($_SESSION["items"] as $cart_itm)
{
echo '<li class="cart-itm">';
echo '<span class="remove-itm"><a href="cart_update.php?removep='.$cart_itm["code"].'&return_url='.$current_url.'">×</a></span>';
echo '<h3>'.$cart_itm["name"].'</h3>';
echo '<div class="p-code">P code : '.$cart_itm["code"].'</div>';
echo '<div class="p-qty">Qty : '.$cart_itm["qty"].'</div>';
echo '<div class="p-price">Price :'.$currency.$cart_itm["price"].'</div>';
echo '</li>';
$subtotal = ($cart_itm["price"]*$cart_itm["qty"]);
$total = ($total + $subtotal);
}
echo '</ol>';
echo '<span class="check-out-txt"><strong>Total : '.$currency.$total.'</strong> <a href="view_cart.php"><button>Check-out!</button></a></span>';
echo '<span class="empty-cart"><a href="cart_update.php?emptycart=1&return_url='.$current_url.'"><button>Empty Cart</button></a></span>';
}
} else {
echo 'Your cart is empty';
}
update_cart
//add item in shopping cart
if(isset($_POST["type"]) || $_POST["type"]=='add')
{
$product_code = filter_var($_POST["product_code"], FILTER_SANITIZE_STRING); //product code
$product_qty = filter_var($_POST["product_qty"], FILTER_SANITIZE_NUMBER_INT); //product code
$price_big = $_POST["priceBig"];
$return_url = base64_decode($_POST["return_url"]); //return url
$productSize = (isset($_GET['productSize']) ? $_GET['productSize'] : null);
//limit quantity for single product
if($product_qty > 10){
die('<div align="center">Please contact us for order of more than 10 quantity!<br /><a href="index.php">Continue to shopping</a>.</div>');
}
//MySqli query - get details of item from db using product code
$results = $mysqli->query("SELECT product_name, price, priceBig FROM items WHERE product_code='$product_code' AND priceBig='$price_big' LIMIT 1");
$obj = $results->fetch_object();
if ($results) { //we have the product info
//prepare array for the session variable
$new_product = array(array('name'=>$obj->product_name, 'code'=>$product_code, 'qty'=>$product_qty, 'price'=>$_POST["productSize"], 'priceBig'=>$obj->priceBig));
if(isset($_SESSION["items"])) //if we have the session
{
$found = false; //set found item to false
foreach ($_SESSION["items"] as $cart_itm) //loop through session array
{
if($cart_itm["code"] == $product_code){ //the item exist in array
$product[] = array('name'=>$cart_itm["name"], 'code'=>$cart_itm["code"], 'price_b'=>$cart_itm["price_b"], 'qty'=>$product_qty, 'price'=>$cart_itm["price"], 'priceBig'=>$cart_itm["priceBig"]);
$found = true;
}else{
//item doesn't exist in the list, just retrive old info and prepare array for session var
$product[] = array('name'=>$cart_itm["name"], 'code'=>$cart_itm["code"], 'qty'=>$cart_itm["qty"], 'price'=>$cart_itm["price"], 'priceBig'=>$cart_itm["priceBig"]);
}
}
if($found == false) //we didn't find item in array
{
//add new user item in array
$_SESSION["items"] = array_merge($product, $new_product);
}else{
//found user item in array list, and increased the quantity
$_SESSION["items"] = $product;
}
}else{
//create a new session var if does not exist
$_SESSION["items"] = $new_product;
// $ans = (isset($_GET['productSize']) ? $_GET['productSize'] : null);
// if ($ans == "PT") {
// $_SESSION["items"] = $new_product;
// } else if ($ans == "QT") {
// $_SESSION["items"] = $new_product;
// }
}
}
//redirect back to original page
header('Location:'.$return_url);
}
Upvotes: 1
Views: 569
Reputation: 12505
I personally advocate for creating functions (or class/methods) that each do their own job. In this case, I would say that you should do that plus change your session array like so:
function addToCart($item)
{
if(!isset($_SESSION['cart']))
$_SESSION['cart'] = array();
$item_code = filter_var($item['product_code'], FILTER_SANITIZE_STRING);
$qty = (!is_numeric($item["product_qty"]))? 1 : $item["product_qty"];
$price['l'] = $item["priceBig"];
$price['s'] = $item["price"];
$size = (!empty($item['productSize']))? $item['productSize'] : 's';
if(isset($_SESSION['cart'][$item_code]))
$_SESSION['cart'][$item_code][$size]['qty'] += $qty;
else {
$_SESSION['cart'][$item_code]['price'] = $price;
$_SESSION['cart'][$item_code][$size]['qty'] = $qty;
}
}
function changeItemSize($item_code,$from = 's',$to = 'l',$qty = false)
{
if(isset($_SESSION['cart'][$item_code][$from])) {
if(isset($_SESSION['cart'][$item_code][$to])){
$useQty = (!$qty)? $_SESSION['cart'][$item_code][$from]['qty'] : $qty;
$_SESSION['cart'][$item_code][$to]['qty'] += $useQty;
$remainder = $_SESSION['cart'][$item_code][$from]['qty'] - $useQty;
if($remainder <= 0)
unset($_SESSION['cart'][$item_code][$from]);
else
$_SESSION['cart'][$item_code][$from]['qty'] = $remainder;
}
else {
$_SESSION['cart'][$item_code][$to] = $_SESSION['cart'][$item_code][$from];
unset($_SESSION['cart'][$item_code][$from]);
}
}
}
if(!empty($_REQUEST['add'])) {
addToCart($_REQUEST);
}
elseif(!empty($_REQUEST['change'])) {
$to = $_REQUEST['productSize'];
$from = ($to == 's')? 'l' : 's';
changeItemSize($_REQUEST['product_code'],$from,$to);
}
Which will give you an array similar to this:
Array
(
[cart] => Array
(
[ITM01] => Array
(
[price] => Array
(
[l] => 14
[s] => 10
)
[s] => Array
(
[qty] => 11
)
)
[ITM02] => Array
(
[price] => Array
(
[l] => 15
[s] => 12
)
[l] => Array
(
[qty] => 5
)
)
[ITM05] => Array
(
[price] => Array
(
[l] => 3
[s] => 2
)
[s] => Array
(
[qty] => 18
)
)
[ITM10] => Array
(
[price] => Array
(
[l] => 12
[s] => 10
)
[s] => Array
(
[qty] => 3
)
[l] => Array
(
[qty] => 1
)
)
)
)
The change function will deduct from a large item to a small item and vice versa. You can play around with it, but those are what I would recommend.
EDIT: Here is what I am kind of trying to get at with my above example. This won't be perfect, but hopefully you get the idea. I would suggest doing this on a whole different space/page incase you can't figure it out, at least you won't wreck what you have.
Couple notes:
1) This system does not require you to go to a whole new page to add stuff to cart. It's all done on one page.
2) Pay attention to the folders and such so you put things in the right spot for inclusion.
3) Finally, this is for demonstration only, use at your own risk. It's not meant to copy and paste, but rather take a look at and see if there is anything that might help you out overall:
/core/classes/class.ShoppingCart.php
// This class is meant to be help keep your cart consistent and contained
// It has all the very basics
class ShoppingCart
{
private $currency;
public function __construct($currency = '$')
{
$this->setCurrency($currency);
}
public function setCurrency($currency)
{
$this->currency = $currency;
}
public function addToCart($item)
{
if(!isset($_SESSION['cart']))
$_SESSION['cart'] = array();
$item_code = filter_var($item['product_code'], FILTER_SANITIZE_STRING);
$qty = (!is_numeric($item["product_qty"]))? 1 : $item["product_qty"];
$price['qt'] = $item["priceBig"];
$price['pt'] = $item["price"];
$size = (!empty($item['productSize']))? $item['productSize'] : 'pt';
if(isset($_SESSION['cart'][$item_code]))
$_SESSION['cart'][$item_code][$size]['qty'] += $qty;
else {
$_SESSION['cart'][$item_code]['price'] = $price;
$_SESSION['cart'][$item_code][$size]['qty'] = $qty;
}
}
public function changeItemSize($item_code,$from = 'pt',$to = 'qt',$qty = false)
{
if(isset($_SESSION['cart'][$item_code][$from])) {
if(isset($_SESSION['cart'][$item_code][$to])){
$useQty = (!$qty)? $_SESSION['cart'][$item_code][$from]['qty'] : $qty;
$_SESSION['cart'][$item_code][$to]['qty'] += $useQty;
$remainder = $_SESSION['cart'][$item_code][$from]['qty'] - $useQty;
if($remainder <= 0)
unset($_SESSION['cart'][$item_code][$from]);
else
$_SESSION['cart'][$item_code][$from]['qty'] = $remainder;
}
else {
$_SESSION['cart'][$item_code][$to] = $_SESSION['cart'][$item_code][$from];
unset($_SESSION['cart'][$item_code][$from]);
}
}
}
public function removeFromCart($item_code)
{
if(isset($_SESSION['cart'][$item_code]))
unset($_SESSION['cart'][$item_code]);
}
public function getCurrency()
{
return $this->currency;
}
}
/core/classes/class.Products.php
// This is just meant to pull some data from your db related
// to your products. You may see some value in expanding this out
class Products
{
private $con;
public function __construct($mysqli)
{
// You need to include the query function
require_once(FUNCTION_DIR.'/function.query.php');
$this->con = $mysqli;
}
public function getProductDetails($itemCodes = false)
{
if(empty($itemCodes))
return query("SELECT * FROM items ORDER BY id ASC",$this->con);
else {
foreach($itemCodes as $codes) {
$val = preg_replace('/[^a-zA-Z0-9]/','',$codes);
$val = trim($val);
if(empty($val))
continue;
$sql[] = "`product_code` = '{$val}'";
}
return query("SELECT * FROM `items` WHERE ".implode(" OR ",$sql)." ORDER BY `id` ASC",$this->con);
}
}
public function getHouseSpecials()
{
return query("SELECT * FROM items WHERE product_type = 'house_specials' ORDER BY id ASC",$this->con);
}
}
/core/functions/function.cartView.php
I would suggest having this as an included html page instead of written into this function directly
// As noted, you would probably save some headache if include() the html
// instead of rendering it in the function directly
function cartView($obj,$currency = '$')
{
ob_start();
?>
<div class="product">
<form method="post" action="">
<div class="product-content">
<h3><?php echo $obj->product_name; ?></h3>
<div class="product-desc"><?php echo $obj->product_desc; ?></div>
<div class="product-info">
<label>
<input id="pt" type="radio" name="productSize" value="pt" checked="checked" />
PT <?php echo $currency.$obj->price; ?>
</label>
<label>
<input id="qt" type="radio" name="productSize" value="qt" class="size_butt" />
QT <?php echo $currency.$obj->priceBig; ?>
</label>
<input type="hidden" name="priceBig" value="<?php echo $obj->priceBig; ?>" />
<input type="hidden" name="price" value="<?php echo $obj->price; ?>" />
Qty <input class="qtyBox" type="number" name="product_qty" value="1" size="3" min="0" />
<input type="submit" name="add" class="add_to_cart" value="Add To Cart" />
</div>
</div>
<input type="hidden" name="product_code" value="<?php echo $obj->product_code; ?>" />
</form>
</div>
<?php
$data = ob_get_contents();
ob_end_clean();
return $data;
}
/core/functions/function.renderCart.php
I didn't finish this function, but you should be able figure it out. It takes the details from the $itemsInCart
and populates the details from looping the cart. Everything after the return
does not work
function renderCart($mysqli,$itemsInCart,$currency = '$')
{
if(empty($_SESSION["cart"]))
return 'Your cart is empty.';
print_r($itemsInCart);
return;
ob_start();
?>
<ol>
<?php if(!empty($_SESSION["cart"])) {
foreach ($_SESSION["cart"] as $itemCode => $cart_itm) {
?> <li class="cart-itm">
<span class="remove-itm"><a href="?remove=true&product_code=<?php echo $cart_itm["code"]; ?>">×</a></span>
<h3><?php echo $cart_itm["name"]; ?></h3>
<div class="p-code">P code : <?php echo $cart_itm["code"]; ?></div>
<div class="p-qty">Qty : <?php echo $cart_itm["qty"]; ?></div>
<div class="p-price">Price :<?php echo $currency.$cart_itm["price"]; ?></div>
</li>
<?php $subtotal = ($cart_itm["price"]*$cart_itm["qty"]);
$total = (0 + $subtotal);
}
?> </ol>
<span class="check-out-txt"><strong>Total : <?php echo $currency.$total; ?></strong> <a href="view_cart.php"><button>Check-out!</button></a></span>
<span class="empty-cart"><a href="cart_update.php?emptycart=1"><button>Empty Cart</button></a></span>
<?php
}
$data = ob_get_contents();
ob_end_clean();
return $data;
}
/core/functions/function.query.php
// This is just a fast and dirty way to run a query and return an array
// It's meant to return, so it's really only good for select statements
function query($sql,$mysqli)
{
$results = $mysqli->query($sql);
if(!$results)
return 0;
while($obj = $results->fetch_object()) {
$row[] = $obj;
}
return (!empty($row))? $row : array();
}
/config.php
// If you don't have some sort of config file with some simple defines and such
// I would encourage it so it's easier to keep track of files and allow
// for the re-use of common elements
//*** Include your database file ***//
// Create some defines (if you don't already have some)
define('ROOT_DIR',__DIR__);
define('CLASS_DIR',ROOT_DIR.'/core/classes');
define('FUNCTION_DIR',ROOT_DIR.'/core/functions');
// Autoload classes
spl_autoload_register(function($class){
if(class_exists($class))
return;
if(is_file($file = CLASS_DIR.'/class.'.$class.'.php'))
include_once($file);
});
/index.php
// Include config
require_once(__DIR__.'/config.php');
// Include the required functions to render
require_once(FUNCTION_DIR.'/function.cartView.php');
require_once(FUNCTION_DIR.'/function.renderCart.php');
// Create instance of products
$pEngine = new Products($mysqli);
// Create shopping cart
$shopEngine = new ShoppingCart('$');
// Do the cart actions if prompted
if(!empty($_REQUEST['add']))
$shopEngine->addToCart($_REQUEST);
elseif(!empty($_REQUEST['change'])) {
$to = $_REQUEST['productSize'];
$from = ($to == 'pt')? 'qt' : 'pt';
$shopEngine->changeItemSize($_REQUEST['product_code'],$from,$to);
}
elseif(!empty($_REQUEST['remove']))
$shopEngine->removeFromCart($_REQUEST['product_code']);
// Quick render of the cart
// This is retrieved from your products list
// This is just an example
$prods = $pEngine->getHouseSpecials();
foreach($prods as $items) {
echo cartView((object)$items);
}
// Quick demonstration of the session
if(!empty($_SESSION['cart'])) {
$details = $pEngine->getProductDetails(array_keys($_SESSION['cart']));
// you would just render the cart here
// This function does not work, I didn't have time
// to finish it...use print_r($details) to see what it returns
// echo renderCart($mysqli,$details,'$');
foreach($itemsInCart as $item_codes) {
if(isset($_SESSION['cart'][$item_codes]['qt']))
echo '<a href="?change=true&product_code='.$item_codes.'&productSize=pt">Item Change to Small</a></br />';
if(isset($_SESSION['cart'][$item_codes]['pt']))
echo '<a href="?change=true&product_code='.$item_codes.'&productSize=qt">Item Change to Large</a></br />';
echo '<a href="?remove=true&product_code='.$item_codes.'">Remove</a></br />';
}
}
Upvotes: 2