Currently doing my computing science assignment and I've chosen to make an online shop, I've used a tutorial to make the shopping basket and everything is working except I can only delete every item except the first one added to my cart. I'd really appreciate any help if possible.
This is where items in my cart are displayed (cart.php):
<?php
session_start();
require_once('db.php');
include('common.php');
?>
<?php getHeader(); ?>
<div class="container">
<div class="row">
<table class="table">
<?php
$items = $_SESSION['cart'];
$cartitems = explode(",", $items);
?>
<?php
$total = '';
$i=1;
foreach ($cartitems as $key=>$id) {
$sql = "SELECT * FROM products WHERE id = $id";
$res = mysqli_query($con, $sql);
$r = mysqli_fetch_assoc($res);
?>
<tr>
<td><?php echo $i; ?></td>
<td>Remove <?php echo $r['name']; ?></td>
<td>£<?php echo $r['price']; ?></td>
</tr>
<?php
$total = $total + $r['price'];
$i++;
}
?>
<tr>
<td><strong>Total Price</strong></td>
<td><strong>£<?php echo $total; ?></strong></td>
<td>Checkout</td>
</tr>
</table>
</div>
</div>
<?php getFooter(); ?>
This is my code that adds an item to my cart(addtocart.php):
<?php
session_start();
if(isset($_SESSION['cart']) & !empty($_SESSION['cart'])){
$items = $_SESSION['cart'];
$cartitems = explode(",", $items);
$items .= "," . $_GET['id'];
$_SESSION['cart'] = $items;
header('location: index.php?status=success');
}else{
$items = $_GET['id'];
$_SESSION['cart'] = $items;
header('location: index.php?status=success');
}
if(in_array($_GET['id'], $cartitems)){
header('location: index.php?status=incart');
}else{
$items .= "," . $_GET['id'];
$_SESSION['cart'] = $items;
header('location: index.php?status=success');
}
?>
This is my delete item code (delcart.php):
<?php
session_start();
$items = $_SESSION['cart'];
$cartitems = explode(",", $items);
if(($_GET['remove']) & !empty($_GET['remove'])){
$delitem = $_GET['remove'];
unset($cartitems[$delitem]);
$itemids = implode(",", $cartitems);
$_SESSION['cart'] = $itemids;
}
header('location:cart.php');
?>
The problem is this line:
if ($_GET['remove'] & !empty($_GET['remove']))
When you want to remove the first item, $_GET['remove'] is 0, which is falsey and also considered empty, so the code that's supposed to remove it doesn't run. Change it to:
if (isset($_GET['remove']) && is_numeric($_GET['remove']))
Also, throughout your scripts you're using & when you should be using &&. & is bit-wise AND, && is logical AND.
When you have only one item in your session,
$cartitems = explode(",", $items);
result is array with "0" index, so if you want to remove last value, $_GET['remove'] should be equal to "0" (example: www.site.loc/?remove=0)
I hope you show us only a sample (not production) code because it is very wrong written and dangerous example:
$sql = "SELECT * FROM products WHERE id = $id"; SHOULD NEVER BE USE!
There's a few things wrong with your code:
1) $_SESSION['cart'] appears to be a string of comma-separated ids, i.e. string(10) "1, 2, 3, 4"
Thus, $cartitems = explode(",", $items) would return an array of those ids, i.e. array(4)[ 1, 2, 3, 4 ]
2) Assuming that $_GET['remove'] is a string containing the item id, i.e. 3
Calling unset($cartitems[$delitem]) would remove the last element of my example array, 4, since arrays are zero-indexed.
To remove the value 3 you'd have to call:
$delitem = array_search($_GET['remove'], $cartitems);
unset($cartitems[$delitem]);
(see http://php.net/array_search)
3) May I please suggest using PDO? http://php.net/manual/en/book.pdo.php
Edit: since I can't comment, Barmar:
Given that OP's items are stored in a database, and id is likely a primary key, it's unlikely that he'd have an item with id of 0 so empty() should be perfectly suitable for his needs. To expound on that point, though, OP, Barmar is correct that in if there are in fact 0 based ids, you'd want to use isset($_GET['remove']) not !empty($_GET['remove'])
See http://php.net/isset and http://php.net/empty for differences.
Your loop and then usage of the variables is the problem:
foreach ($cartitems as $key=>$id) {
...
<td>Remove <?php echo $r['name']; ?></td>
...
}
The $key should be $id
When using foreach this way, the $key var is the array index and the $id is the value (which could be a string, array, object, int...).
http://php.net/manual/en/control-structures.foreach.php
But since you don't care about the array index here, you can simply omit it from the foreach declaration:
foreach ($cartitems as $id) {
and it will work identically.
Related
Context: I have an ordering form, that has a html select and a number input. so a user selects the item and enter the amount they want of that item, these are sent as arrays to the hander page. $_POST['item']; is an array of id's that I want to select product info from the database with. $amount = $_POST['amount']; is just an array of the amounts of each item.
Problem: Each row is being duplicated by the amount of rows there are, so in this case it's returning three rows, but duplicating each one, three times.
Objective: All I'm trying to do is foreach $_POST['item'] get that rows data from the database and show them and the respective amounts in a table, so the user can confirm the order.
handle.php
<?php
$item = $_POST['item']; // array of product ids to select data from db
$amount = $_POST['amount']; // array of amounts of each product the user ordered
$note = $_POST['note'];
$i = 0;
$each = implode(',',$item);
$stmt = $dbh->query('SELECT *
FROM `products`
WHERE `id` IN (' . $each . ')');
<table class="table">
<thead>
<tr>
<th scope="col">Item</th>
<th scope="col">Quantity</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<?php
while ($row=$stmt->fetch(PDO::FETCH_ASSOC)) {
$product_id = $row['id'];
$product_name = $row['name'];
$product_price = $row['price'];
$row['quantity'] = $amount[$row['id']];
print "<pre>";
print_r($row);
print "</pre>";
?>
<tr>
<td><?php echo $product_name;?></td>
<td><?php echo $row['quantity'];?></td>
<td><?php echo $product_price;?></td>
</tr>
<?php } ?>
</tbody>
</table>
I'm not really sure what you're trying to do, but you are reassigning
$key = array() ;
immediately after your
foreach ($amount as $key)
That's causing your
<td><?php echo $key;?></td>
to try to echo an array because you overwrote the value of $key assigned by the foreach.
Your post does not detail what data is getting duplicated so I can't really address that in this answer.
You are duplicating the same three rows because you are setting
$new = array_combine($item, $amount);
Then your SQL is grabbing the rows
$stmt = $dbh->query('SELECT *
FROM `products`
WHERE `id` IN (' . $each . ')');
Then you're looping over the same items with
foreach ($new as $key => $val) {
If you want to display the items you found in the SQL then you shouldn't have the
foreach ($new as $key => $val) {
inside your while() loop. Your while() is already looping over the rows returned for those items. This assumes you only have one product per item number.
If you expect one or more 'products' to be returned for each item number then you should be executing your SQL while looping through foreach($new), but that doesn't appear to be what the top part of your code is doing.
After some back and forth we've identified the issue: the amounts need to be tied to the item numbers.
You are getting items numbers and quantities as arrays from your HTML. So you need to loop through the items and associate them with your quantities.
// where your qualities will live
$quantities = array() ;
// loop through the array of items you received and match them up with their quantity
foreach($item as $k=>$id) {
$quantities[$id] = $amount[$k] ;
}
Then you can access the quantity in your while loop using:
$row['quantity'] = $quantities[$row['id']] ;
Before add it to cart i want to check if that item already exist. If item exist i dont want twice to show the some item in looping. Just increment quantity of existing item in array session.
Session array with items in cart:
Array
(
[0] => Array
(
[id] => 1
[qty] => 1
)
[1] => Array
(
[id] => 1
[qty] => 1
)
)
On Cart page where am looping items form cart i have this:
<?php
$db = require('database.php');
$cart_items = isset($_SESSION['cart']) ? $_SESSION['cart'] : null;
$products = array();
if($cart_items):
foreach ($cart_items as $key => $value)
{
$products[$key] = $value;
$id = (int) $value['id'];
$result = $db->query("SELECT * FROM products WHERE id=$id");
while($row = $result->fetch_object())
{
$products[$key]['id'] = $row->id;
$products[$key]['name'] = $row->name;
$products[$key]['price'] = number_format($row->price, 2);
// check if item exists
// this dont work i dont know how to check this
if($id == $row->id && $value['qty'] == 1)
{
$products[$key]['qty']++;
}
}
}
endif;
?>
And fronted part where i loop cart products:
<tbody>
<?php if($products): ?>
<?php foreach ($products as $product): ?>
<tr>
<td><?= $product['id'];?></td>
<td><?= $product['name'];?></td>
<td><?= $product['price'];?> Eur</td>
<td><input type="text" name="qty" value="<?= $product['qty']; ?>" size="5"> </td>
<td> <i class="glyphicon glyphicon-remove"></i> Remove </td>
</tr>
<?php endforeach; ?>
<?php endif;?>
</tbody>
So problem is when i click 2 times on item with id = 1 i get two new table rows with the some products. My idea is when i click 2 times on product id = 1 just increment quantity on existing product in cart.
Any sugestion for this ?
First of all, use array_column() function to get all the existing product ids from the $products array. And then check whether the particular item exists in the $products array or not, and update the product and/or quantity details accordingly.
So your while() loop should be like this:
while($row = $result->fetch_object()){
$ids = array_column($products, 'id');
if(in_array($row->id, $ids)){
$products[$key]['qty']++;
}else{
$products[$key]['id'] = $row->id;
$products[$key]['name'] = $row->name;
$products[$key]['price'] = number_format($row->price, 2);
$products[$key]['qty'] = 1;
}
}
Also, remove this statement from your foreach loop,
$products[$key] = $value;
Updated:
From OP's comment,
Now problem is in looping products in cart, when i loop products in cart i have duplicate product becouse i add one product 2 times and update quantity. How to prevent double looping one item in cart! If i press 10 times product with id = 1. I dont want 10 new loop items in list i want only update quantity value. Prevent the some item loop in <tr><td> ...</td></tr> ...
Change your code inside the if block in the following way,
$unique_ids = array_unique(array_column($cart_items, 'id'));
foreach ($cart_items as $key => $value){
if(!in_array($value['id'], $unique_ids)) continue;
$id = (int) $value['id'];
$result = $db->query("SELECT * FROM products WHERE id=$id");
while($row = $result->fetch_object()){
$ids = array_column($products, 'id');
if(in_array($row->id, $ids)){
$products[$key]['qty']++;
}else{
$products[$key]['id'] = $row->id;
$products[$key]['name'] = $row->name;
$products[$key]['price'] = number_format($row->price, 2);
$products[$key]['qty'] = 1;
}
}
$key = array_search($value['id'],$unique_ids);
unset($unique_ids[$key]);
}
Ok, I have this code
<?php //getting values
$column1 = $params->get('param1','');
$column2 = $params->get('param2','');
$column3 = $params->get('param3','');
$column4 = $params->get('param4','');
$column5 = $params->get('param5','');
//setting array and filter the empty values
$getvalues = array($column1,$column2,$column3,$column4,$column5);
$values = array_filter($getvalues); ?>
then I am using these values inside a foreach
<?php foreach ( $values as $key=>$value ) : ?>
<div><?php echo $value; ?></div>
<?php endforeach; ?>
It does the job, but after the loop, it adds the last item's value. Why?
After a foeach loop the used $key and $value variables are still alive and holds their last values so i think you are using the $value somewhere else in you code whithout rewriting it's value.
Call unset($value) and unset($key) after the loop and watch the PHP errors i think you will face some if the error reportnig is set to the most strict mode.
I thought this was quite basic but for some reason I can't figure it out.
I have this query
$result = mysql_query("SELECT * FROM Users.Information LIMIT 0,1");
To grab the data (such as firstName, lastName), I use this snippet of code
<?php while ($row = mysql_fetch_assoc($result)): ?>
<?php foreach($row as $key=>$value) {
echo $value;
} ?>
<?php endwhile; ?>
which correctly prints everything I want.
Now in a separate table, I want to have it such that I will print the individual values separately. I thought this was quite simple like
first name:
however, this does not work. If I just do $value, of course this makes sense, but it prints the last value in the array.
How do I grab individual values? Do I just parse $value into different values, or is there an easier way?
Thank You.
$data = array() ; //Create a storage, so you can access it later.
<?php while ($row = mysql_fetch_assoc($result)): ?>
$data[] = $row ; //Add the value to storage.
<?php foreach($row as $key=>$value) {
echo $value;
} ?>
<?php endwhile; ?>
We are ready. We have $data array with all rows. Now you can manipulate it, access elements, pass somewhere.
$data[0] ; //Access the first element
echo $data[0]['FirstName'] ; //Print first name of the first row.
I'm pulling some data from a database (with a function I have called query), and I want to add another key/value pair to each result, i.e.:
$items = query("SELECT * FROM items");
foreach($items as &$item) {
$item['fixedname'] = str_replace(' ','_',$item['name']);
}
Now I want to put these on an html view, i.e.:
<?php foreach($items as $item): ?>
<div id="<?= $item['fixedname'] ?>" ><?= $item['name'] ?></div>
<?php endforeach; ?>
However, this doesn't output correctly. For instance, when the query returns two items, the loop in the php outputs the same thing twice. If there are three: it outputs the first one, then two of the second one. What's the problem here?
When modifying using foreach() I've had weird results on occasion. I use
foreach ($items as $key=>$value) {
$items[$key] = modified($value);
}
Or, why not do it in the SQL SELECT your, fields, here, REPLACE(name, ' ', '-') AS fixedname
The data returned on the right side of the foreach is a copy of the data, it can't be modified directly. Instead you need to fetch both the $key (the ID of the item in the array) and the $item. By letting PHP telling you the $key you don't need to worry about whether the array is normal (e.g. having indexes of 0,1,2,...) and associative.
This example would walk the $items array and add 'fixedname' into it.
foreach($items as $key => $item) {
$items[$key]['fixedname'] = str_replace(' ','_',$item['name']);
}
You could do a normal for loop
<?php
for($i=0; $i < count($items); $i++){
$items[$i]['fixedname'] = str_replace(' ','_',$items[$i]['name']);
}
?>
Then everything will be ready when you go to your next foreach.
u have bunch of wrong things
1- dont use mysql , use PDO or mysqli instead
2- $items = query("SELECT * .... --->Call to undefined function query()
change it to
$items = mysql_query("SELECT * ....
3- Invalid argument supplied for foreach() ,
you missed to fetch your query
try this whole code
$items = mysql_query("SELECT * FROM items");
?>
<?php while ($row = mysql_fetch_array($items) ) {?>
<div id="<?php echo $row['fixedname'] ;?>" ><?php echo $row['name']; ?></div>
<?php } ?>