Creating a cart

I want to create a shopping cart for myself. In each step they can add products to the cart, apply coupon etc… The items on cart were sessioned when taking each step of cart. Finally an array of cart info were sessioned. After login that array was inserted into db as an order then pay. I had problem that after adding items to my cart, on last step if I had not an account, first I had to create an account and when login, sometimes that array session was cleaned and I had to repeat ordering on cart again. So on last step of cart, I did serialize the array and save it to db, after login it checks if the user has a cart session in db, it generates an order for him. Now I want to improve it a better way, can you suggest how would you implement a cart?

first I had to create an account and when login, sometimes that array session was cleaned and I had to repeat ordering on cart again
You were destroying the session somehow, I guess, instead of updating the existing session with the fact this is now a registered user logged in. If you fix that you shouldn’t need to store the session data anywhere else temporarily.

I was not destroying the session by command, and actually on my installation I had not such problem, in fact some users of my cart reported to me they have such problem! Anyway what is the best way to handle items on cart?

Anyway what is the best way to handle items on cart?
Can you be more specific? If you mean how would I implement a shopping cart I’d probably say I’d use a table called Cart with fields id, userId, productId, and qty.

I like the idea of using a database instead of sessions because I don’t think it is good to have carts magically empty themselves. I occasionally put things in an Amazon cart, don’t buy them, and then return many weeks later and find it rather delightful that they are still in there.

In fact you could probably generalize the table I just suggested to handle both registered and unregistered users.

Can you explain more? On each step you’d save them on cart table and on last step you create an order and delete tge info from cart table?

OK so, you have a tables that look like this:

User { id, name, dateRegistered ... }
Product { id, name, price, ... }
Cart { id, productId, userId, qty }

1. Unregistered user starts using the site

A session will be created by virtue of session_start() being called at the top of every page that could need to reference the cart.

2. Unregistered user adds an product to cart

Add the productId to the session.

if (isSet($_POST['product-id']) && $_POST['form-id'] === 'cart-add') {
   $productId = (int)$_POST['product-id'];
   // TODO: validate `$toAddToCart` exists in Product table
   if (!isSet($_SESSION['cart'])) {
      $_SESSION['cart'] = array(); }
   if (isSet($_SESSION['cart'][$productId])) {
      $_SESSION['cart'][$productId]++; }
   else { $_SESSION['cart'][$productId] = 1; } }

3. Unregistered user adds same product to cart a second time

Above code handles that already

4. Unregistered user attempt to pay

Bounce the user to the registration page. Only registered users can submit an order.

5. Unregistered user registers

Do this however you would normally. Only at the end add this:

if (isSet($_SESSION['cart'])) {
   $q = 'INSERT INTO `Cart`(`userId`, `productId`, `qty`) VALUES ';
   $tuples = array();
   foreach ($_SESSION['cart'] as $productId => $qty) {
      $tuples[]=  '(' . (int)$userId . ', '. (int)$productId . ', '. (int)$qty . ')'; }
   mysqli_query($db, $q . join(',', $tuples));

6. Now registered user adds another product to cart

Now we can see that the code in 2 has to be expanded to handle the registered users as well.

if (isSet($_SESSION['user'])) { // user is logged in
   /* switching to psuedocode */
   If row with this productId already exists // select query required
      update row: qty++
      insert row with userId, productId, and qty of 1
else { /* code from 2 */ }

6. Registered user completes order

SELECT from Cart to see what to charge the user for

Thanks. But what about order info in order table? In your ecample your cart table is yhe same as order table? Or you’d create it when payment is done?

Ah OK. You’ll need two additional tables for that:

Order { id, userId, ... }
OrderItems { id, orderId, productId, qty }

When the user places an order copy SELECT from Cart to INSERT INTO Order and OrderItems. Then 'DELETE FROM Cart WHERE userId = ’ . (int)$userId