Doss Smart Doss Smart - 3 months ago 12
PHP Question

How to append an associative array to the end of another array?

I am working on my cart for a project and having issue. I have really tried to sort it out myself but same issue.
Basically people will select shoes size from a dropdown menu to be sent to the cart. and the code will check :


  • -if there is already value in the session cart : if same value for id and size, then we increase the qty of the existing value

  • -if there is already value in the session cart : if the id value is same, but the size value different, then it is a new value, append to
    the existing value.

    For the first check the code work fine, it checks the existing values in the session cart and if it is the same id and same size, the qty increase fine.

    the issue is in the second check: when i select another size in the dropdown but with the same item id, the new value (id and size) just erase the existing values in cart.



What i want is that: if item id is same, but has a different size, then it is a new value and that array value need to be appended to end of the session cart as a new value

Here is my code:

<?php
$items = array(
array('id' => '1', 'desc' => 'sneaker','price' => 24.95, 'size'=>'424546'),
array('id' => '2', 'desc' => 'Reebok','price' => 200, 'size'=>'323845'),
array('id' => '3', 'desc' => 'Songs of the Goldfish (2CD set)','price' => 19.99),
array('id' => '4', 'desc' => 'Simply JavaScript (SitePoint)', 'price' => 39.95)
);

session_start();
if (!isset($_SESSION['cart'])) {
$_SESSION['cart'] = array();
}

if (isset($_POST['action']) and $_POST['action'] == 'Buy') {
$size="";
//Get the values for the post and make sure they are integers
$pid = filter_var( $_POST['id'], FILTER_VALIDATE_INT, array('min_range'=> 1) );
$size = $_POST['doSize'];
if (isset($_SESSION['cart'][$pid])) {

foreach ($_SESSION['cart'] as $key) {

if ($key['id'] === $pid and $key['size'] !== $size) {
echo "NOT SAME SIZE";
$si = $size;
$_SESSION['cart'][$key['id']] = array('id'=>$pid, 'size'=>$si, 'quantity'=>1);

}

elseif ( $key['id'] === $pid and $key['size']=== $size ) {
$_SESSION['cart'][$key['id']]['quantity']++;
echo "YES CORRECT";
}
}//end foreach
print_r($_SESSION['cart']);
}//end isset session cart

else{
$_SESSION['cart'][$pid]= array('id'=>$pid, 'size'=>$size, 'quantity'=>1);

foreach ($_SESSION['cart'] as $key) {
echo $key['id'];
}

print_r($_SESSION['cart']);
}
}//END POST
include'cat.html';

//unset($_SESSION['cart']);
?>


Here the cart.html

<!DOCTYPE html>
<head>
<title>Product catalog</title>
<meta http-equiv="content-type"
content="text/html; charset=utf-8" />
<style type="text/css">
table {
border-collapse: collapse;
}
td, th {
border: 1px solid black;
}
</style>
</head>
<body>
<p>Your cart contains <?php echo count($_SESSION['cart']);?> item(s).</p>
<p><a href="?cart">View your cart</a></p>
<table border="1">
<thead>
<tr>
<th>Item Description</th>
<th>Price</th>
<th>Size</th>
</tr>
</thead>

<tbody>
<?php foreach ($items as $item): ?>
<tr>
<td><?php echo $item['desc']; ?></td>
<td>
$<?php echo number_format($item['price'], 2); ?>
</td>
<td>

<form action="" method="post">

<?php if (isset($item['size'])) { ?>

<select name="doSize">
<?php foreach(str_split($item['size'], 2) as $size):?>
<option value="<?php echo $size;?>"><?php echo $size;?></option>
<?php endforeach;?>


</select>
<?php }?>
</td>

<td>
<div>
<input type="hidden" name="id" value="<?php echo $item['id']; ?>"/>
<input type="submit" name="action" value="Buy"/>
</div>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p>All prices are in imaginary dollars.</p>
</body>
</html>

Answer

Your foreach loop is wrong. When you see a cart entry with a different ID or size from the one the user selected, it doesn't mean it's not found, because it could be in a different element of the array. You need to wait until you get to the end of the loop to know whether the item was found.

$found = false;
foreach ($_SESSION['cart'] as &$key) {
    // Use &$key reference so we can modify the element
    if ( $key['id'] === $pid and $key['size']=== $size ) {
        $key['quantity']++;
        echo "YES CORRECT";
        $found = true;
        break;
    }
}//end foreach
if (!$found) {
    $_SESSION['cart'][] = array('id' => $pid, 'size' => $size, 'quantity' => 1);
}

Also, you can't use $pid as the key of $_SESSION['cart'], since you can have different sizes with the same $pid, and an associative array can't have multiple elements with the same key.