Php shopping cart crashing - uses large php array

I am having trouble with a shopping cart that I built using PHP. It seems that some members are experiencing some kind of crash after putting more than roughly 20 to 30 items in the cart and they lose all of the items. I’ve tried this on my own browsers and it works fine.

One customer took a screenshot of the error and it appears in an automated script that checks the available quantity for every item in the cart array each time a new item is added. Each item number, quantity and shipping type is stored in a single array called $cart. My little script uses MySQL to selects the quantity in my products table for each id number of the item. This loop all happens before the new item is added to the cart.

I was wondering if anyone had suggestions about what might be happening.

Thanks

Correction, I did just experience a crash when I added just over 100 items…

It worked just fine until I added one more item and all the sudden this error message loops about 100 times like:
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/…/cart.php on line 20

When I go back again, all of the items in the cart are gone!

Can you post a few lines of cart.php (including line 20), here?

Well, I don’t think it’s my code, it works perfectly fine, the logic seems solid and then out of nowhere, the cart array just screws up and crashes.

After more experimenting adding about 30 items, I got this new odd error:
No database selected

My array did not crash and lose all of my items, but this is the first time I’ve seen this error. I don’t think this has anything to do with my code, it seems like something going on in the background or possibly a PHP bug that causes a random crash and weird errors…

Does this kind of behavior sound familiar to you?

Line 20 of my code is just a simple mysql query, it’s running a check for each item from each seller in the shopping cart:
for each seller {
for each item id {
18 $sql = “SELECT quantity FROM items WHERE id = ‘$id’”;
19 $result = mysql_query($sql) or die(mysql_error());
20 $row = mysql_fetch_array($result);

}
}

Well, I don’t think it’s my code, it works perfectly fine, the logic seems solid and then out of nowhere, the cart array just screws up and crashes.

You’re wrong. :wink:

You’re querying the database in a loop, so 100 items, a 100 queries; this is bad. What you’re looking for is…

SELECT this FROM that WHERE id IN (1,2,3,4,5,6) 

One query, for all the ids.

Next time you get a “crash” have a look at MySQL’s log (probably called something like mysql.log), any of the entries from around the same time stick out?

Thanks for the response…

huh, I query the database in loops many times on my site, this is a new kind of query that I am not familiar with. Do you think my MySQL query could have anything to do with my $cart array suddenly being deleted? I figured this would be independent of each other.

Well here is my full code then:


$cart = $_SESSION['cart'];
foreach($cart as $seller=>$sellerstuff) {
  foreach ($cart[$seller] as $id=>$itemstuff) {
    $sql = "SELECT quantity FROM items WHERE id = '$id'";
    $result = mysql_query($sql) or die(mysql_error());
    $row = mysql_fetch_array($result);	
    //....  do conditional array modification stuff  ....
  }
}
$_SESSION['cart'] = $cart;

Note that $cart[$seller][$id] is an array that can hold:
$cart[$seller][$id][‘quantity’]
$cart[$seller][$id][‘shippingtype’]

How would you program the above code and MySQL query so that it works properly, won’t crash the $cart array and won’t do anything bad?

Thanks
Kind regards

Do you know if the mysql.log is typically available on a shared hosting service?

Thanks
Kind regards

It’s difficult because I’m not really sure what you’re trying to do, but I’ll have a bash. :slight_smile:


<?php
$cart = array(
	'amazon' => array(
		12 => 'books',
		45 => 'pans',
	),
	'ebay' => array(
		2 => 'games',
		5 => 'calculator',
	),
);


foreach($cart as $seller => $items)
{
	$ids = implode(',', array_keys($items));
	$sql = sprintf("SELECT quantity FROM items WHERE id IN (%s);", $ids);
}

Ideally though, you’d want to only have one query and add some jiggery pokery using PHP.


<?php
$cart = array(
	'amazon' => array(
		12 => 'books',
		45 => 'pans',
	),
	'ebay' => array(
		2 => 'games',
		5 => 'calculator',
	),
);


$ids = '';


foreach($cart as $seller => $items)
{
	$ids .= ',' . implode(',', array_keys($items));
	
}


$sql = sprintf("SELECT seller, quantity FROM items WHERE id IN (%s);", $ids);

All untested, but hopefully you get the point; no mater how poorly made. :wink:

Anthony.

Thanks for the response, this seems to be working so far.

I’m not familiar with sprintf() and “%s” in your query. What is the different between:
$sql = “SELECT id,quantity FROM items WHERE id IN ($ids)”; and
$sql = sprintf(“SELECT id,quantity FROM items WHERE id IN (%s);”, $ids);

This is what I’ve gotten so far:

$cart = $_SESSION['cart'];
foreach($cart as $seller=>$items) {
  $ids = implode(',', array_keys($items));
  $sql = "SELECT id,quantity FROM items WHERE id IN ($ids)";
  $result = mysql_query($sql);
  while($row = mysql_fetch_array($result)) {
    $id = $row['id'];
    if ($cart[$seller][$id]['quantity'] > $row['quantity']) {
       $cart[$seller][$id]['quantity'] = $row['quantity'];
    }
    if ($row['quantity'] == 0) {
       unset($cart[$seller][$id]);
    }
  }
}
$_SESSION['cart'] = $cart;

So essentially, I’ve reduce a query for every item down to a query for every seller. Typically, visitors won’t be purchasing from more than 1 or 2 sellers at a time.

Let me know what you think about this and what the benefits of the sprintf command does.

Thanks
Kind regards

This is the manual entry on [fphp]sprintf[/fphp]. I’ve seen it many times, but have never seen the point in using it. It seems to want to occupy the (non-existent IMO) gap between PHP’s inbuilt string parsing and the genuinely complex string parsing allowed for by [fphp]preg_replace[/fphp]. In 8 years I’ve never wrote code to use it, and when I’ve had to edit code with it I’ve either left it alone or pulled it out.