Question

I am doing a simple shopping application were user may choose books from the store based on the title, price, quantity etc. At the moment all details of the books are kept in an associative array which looks like this:

$menu = array(
array ('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),

array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss'),);

}

What I am trying to achieve is merge or remove duplicated entries of book id's also each book title will be printed in one single row containing 'title', 'id', 'price'

for example:

  1. Alex qty:2 price 4.95
  2. David qty:2 price 5.95 and so on...

And this is my cart file:

        $buy = array();
        $qty = 0;
        $total = 0;
        foreach ($_SESSION['buy'] as $id) {


            foreach ($menu as $book ) {

                if ($book['id'] == $id) {
                    $buy[] = $book;
                    $total += $book['price'];

                }
            }
        }
    }


    if (count($buy) > 0)
        if (count($book) > 0)
    {
        echo"<table>";
        echo"<tr><th>Item Description</th><th>Quantity</th><th>Price</th></tr>";

        foreach ($buy as $book){


            $f_price = sprintf("%0.2f", $book["price"]);

            echo"<tr><td>" .$book["title"] ."</td>";
            echo"<td>" .$qty."</td><";
            echo"<td>" .$f_price."</td></tr>";
        }

        echo"<tr><td>Total</td><td>".$total."</td></tr>";
        echo"</table>";
    }

I will be extremely grateful for any help or advice cause I spent long long time to resolve this problem trying use unique functions, for statements foreach loop but in vain I am still novice also please try to be a little tolerant . Cheers!

Was it helpful?

Solution

Untested but this should do what you want using array_count_values to obtain the quantities you were looking for along with a few changes to make the script more efficient and easier to manage.

<?php
//the ids of the items the user wants to buy
$ids=$_SESSION['buy'];

//Your database of items
$menu = array(
    array ('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
    array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss')
);
//Create a reverse look-up for the database
$lookUp=array();
foreach($menu as $i=>$v)$lookUp[$v['id']]=$menu[$i];



//populate the cart with items, their quantities, and a total
$cart = array();
$total = 0;
foreach (array_count_values($ids) as $id=>$quantity)
{

    if (!array_key_exists($id, $lookUp))continue;
    $item=$lookUp[$id];
    $itemTotal=$item['price']*$quantity;
    $total+=$itemTotal;
    $cart[]=array_merge($item,array('quantity'=>$quantity,'itemTotal'=>$itemTotal));
}


if(count($cart) > 0)
{
    echo '<table>';
    echo '<tr><th>Item Description</th><th>Quantity</th><th>Price</th><th>Item Total</th></tr>';
    foreach ($cart as $item)
    {

    echo sprintf('<tr><td>%s</td><td>%s</td><td>%0.2f</td><td>%0.2f</td></tr>',
        $item["title"],$item['quantity'],$item['price'],$item['itemTotal']);
    }
    echo '<tr><td colspan="3" style="text-align:center;">Total</td><td>'.$total.'</td></tr>';
    echo '</table>';
}

OTHER TIPS

If it's just based off the id, when you build the array, store the book id as the key in the larger array, so your end array would be:

$books = array(
   1=> array ('id' => '1', [...]),
   2=> array ('id' => '2', [...])
);

You could also add some code that checks when you try to assign a value to that array to see if the key is already set.

if(!isset($books[$book_id])){
  //Add to the array
}else{
   //Maybe display an error?
}

PS: Category only has one a in it.

It's a pretty cumbersome way to make a stock overview of the books in your collection, but that aside :)

If i was to work with an array like that, (and i would never do that :)) i would first select all unique keys, and then go through them one by one, counting the number of times it occur in the $menu array. As follows:

$unique_books = array_unique($menu);

foreach($unique_books as $book){

 $qty = array_keys($menu, $book["id"])
 $book["qty"] = $qty;
 $stock = $book;

}

As you can see, now $stock will be the unique array, with a qty added to it, containing the number of times, the id was seen in $menu. This is just a fast code block, and should be testet, but the theory works i think. As i mentioned before, the way you'r making this in the first place, is not very smart, and you should really reconsider the whole thing imo :)

If you don't wanna duplicates simple use the book_id as the key of buy array

Example:

 $menu = array(
    array('id' => '1', 'catagory' => 'newbooks','title' => 'Alex','price' => 4.95, 'desc' => 'bbbb'),
    array('id' => '2','catagory' => 'newbooks','title' => 'David ','price' => 5.95, 'desc' => 'sss')
);
$session=array(1,2,2,2,1);
$buy = array();

        foreach ($session as $id) {
            foreach ($menu as $book) {
                if ($book['id'] == $id) {
                    if(isset($buy[$id])){
                        $buy[$id]['qty']++; // increase quantity
                        $buy[$id]['total'] += $book['price']; // total price only for this id
                        $buy['total'] += $book['price']; // All ids price total
                    }else{
                        $buy[$id] = $book; // assign new id to the buy array
                        $buy[$id]['qty'] = 1; // quantity reset to 1
                        $buy[$id]['total'] = $book['price']; // id price
                        $buy['total'] += $book['price']; // total price
                    }
      }  
   }
}
print_r($buy);

You can test it here!

http://codepad.org/wH2WskLG

Instead of merging duplicates you should add book id and qty as array row to session.

On session start..

if (!isset($_SESSION['buy']))
  $_SESSION['buy'] = array();

When adding new..

$new_book = $added_book; // just for example
$qty = $added_qty; // Added qty

// Check if book already exists in shopping cart and update qty
if (array_key_exists($new_book['id'], $_SESSION['buy'])) {
   $_SESSION['buy'][$new_book['id']] += $qty;
} else {
   $_SESSION['buy'][$new_book['id']] = $qty;
}

Then on shopping cart view just loop thru your items..

 foreach($menu as $book ) {


   if (array_key_exists($book['id'], $_SESSION['buy'])) {
      // User bought this book..

      $qty = $_SESSION['buy'][$book['id']];
   }

 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top