PHP Shopping Cart

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
I hit a wall where I cannot figure out what is wrong with the block of code in this page. It is a simple shopping car script that when given the correct URI, it will add an item to the shopping cart.
PHP:
session_start();

$query = "SELECT ID FROM Items WHERE ID = " . mysqli_real_escape_string($con,$_GET["id"]);

if ($_GET["do"] === "add" && @mysqli_query($con,$query)) {
    if (isset($_SESSION["cart_id"])) {
        if (array_search($_GET["id"],unserialize($_SESSION["cart_id"])) === false) {
            $_SESSION["cart_id"] = serialize(array_push(unserialize($_SESSION["cart_id"]) , $_GET["id"] ));
            $_SESSION["cart_qty"] = serialize(array_push(unserialize($_SESSION["cart_qty"]),1));
        }
    }
    else {
        $_SESSION["cart_id"] = serialize(array($_GET["id"]));
        $_SESSION["cart_qty"] = serialize(array(1));
    }
}
The code on lines 8 and 9 are the problem, and its doing something weird to the arrays. Whats wrong with it or is there a better cod snippet I should be using? :dunno:

If you visit the page, for diagnostic purposes, the shopping cart is printed to the screen. Adding ?do=clear to the URL will unset the session data.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
array_push returns the new array size, not a new array. That's what's replacing the serialized arrays in the session variables with serialized ints.

You don't have to serialize session data. PHP will handle that for you. Also, you should use associative arrays to store cart data. It's much more efficient (array_search is O(n), while associative arrays are O(log(n)) for tree implementations and O(1) for hash implementations).

PHP:
session_start();
if (!isset($_SESSION["cart"])) {
    $_SESSION["cart"] = array();
}
// itemExists() should be in the file that handles DB access
function itemExists($id) {
    $query = $con->prepare("SELECT ID FROM Items WHERE ID=?");
    $query->bind_param('i', $itemID);
    return @$query->execute() && $query->num_rows;
}

$itemID=isset($_GET["id"])  ? $_GET["id"]  : -1;
$qty   =isset($_GET["qty"]) ? $_GET["qty"] :  1;

if (itemExists($itemID)) {
    switch ($_GET['do']) {
    case 'add':
        if (isset($_SESSION["cart"][$itemID])) {
            $_SESSION["cart"][$itemID] += $qty;
        } else {
            $_SESSION["cart"][$itemID] = $qty;
        }
        break;
    case 'remove':
        unset($_SESSION["cart"][$itemID]);
        break;
    // other actions ...
    default: // unknown action.
        echo "Error: I don't know what you want me to do. What is '$_GET[do]'?";
        break;
    }
}
 

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
My PHP book says specifically to serialize the array? Well not having to makes the scripts that much easier.

Thanks a lot misson!
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
As long as you're using PHP sessions, you don't need to serialize or unserialize data, even if you're using user sessions. You'll only need serialize & unserialize if you storing persistent data outside of PHP sessions.

When does the book say to use serialize/unserialize?
 
Last edited:

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
Here is the example:

PHP:
<?php
session_start();
?>
<html>
<head>
<title>Storing an array with a session</title>
</head>
<body>
<h1>Product Choice Page</h1>
<?php
if (isset($_POST["form_products"])) {
	if (!empty($_SESSION["products"])) {
		$products = array_unique(
		array_merge(unserialize($_SESSION["products"]),
		$_POST["form_products"]));
		$_SESSION["products"] = serialize($products);
	} else {
		$_SESSION["products"] = serialize($_POST["form_products"]);
	}
	echo "<p>Your products have been registered!</p>";
}
?>
<form method="POST" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
<P><strong>Select some products:</strong><br>
<select name="form_products[]" multiple="multiple" size="3">
<option value="Sonic Screwdriver">Sonic Screwdriver</option>
<option value="Hal 2000">Hal 2000</option>
<option value="Tardis">Tardis</option>
<option value="ORAC">ORAC</option>
<option value="Transporter bracelet">Transporter bracelet</option>
</select>
<P><input type="submit" value="choose"/></p>
</form>
<p><a href="session1.php">go to content page</a></p>
</body>
</html>
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Either the book was written for a very old version of PHP or the author doesn't know what zhe's talking about in that example.
 

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
No, it was written for Sams publishing which has a strictly short format. He probably wanted to cram as many functions in that book as possible :)
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
So it's just a restricted format leading to poor technical writing? The author shouldn't have written a misleading example, as it will be copied and live on in reader's code (Joshua Bloch mentions this in the context of API design; if the google video link doesn't work, try youtube). Misusing functions is arguably worse than not introducing them, as it provides information that needs to be unlearned, and learning is easier than unlearning. serialize/unserialize are useful for storing PHP data outside of PHP, such as in a database. If the author didn't want to include such a scenario, or couldn't find a way to include it given format restrictions, he could have introduced serialize/unserialize without a usage example, which wouldn't be as useful for the reader but would at least wouldn't have been misleading. At the very least, he could have written a note explaining that the example was merely an illustration and you don't need to serialize or unserialize PHP session data in production code. This is by far the worst option, as someone skimming the book for code samples would miss the caveat.

I'm being rather hard on the author in this one limited case, true. I imagine the rest of the book is better written.
 

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
Yes, I believe you were right. The book did not include any real description of what the function was used for, and I did assume it was a necessary part of the script. The book however is written very well and managed to introduce me to the concepts of Apache, MySQL and PHP in one 564 page book. THanks for your correction to the book, as well as your example of OOP =)
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
You're very welcome, except I don't know where I gave an OOP example. It's all procedural programming, as far as I can see.
 

xav0989

Community Public Relation
Community Support
Messages
4,467
Reaction score
95
Points
0
You're very welcome, except I don't know where I gave an OOP example. It's all procedural programming, as far as I can see.
It's the Book! It's maybe teaching that second level associative arrays is OOP... getting better by the second! :biggrin:

For your information, OOP is when you use classes such as :
PHP:
<?php
class Whatever {
    public function someThing() {
        return 'someThing() just executed in OOP';
    }
}

$oop = new Whatever;

$oop->someThing();
Whatever::someThing();
?>
A little trick: when you see :: or -> , it's OOP, else , it's procedural.
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
It's not that I don't know how to recognize OOP (boy, can I), it's that I didn't notice any in the examples posted thus far. Then I did, in my itemExists:
PHP:
function itemExists($id) { 
    $query = $con->prepare("SELECT ID FROM Items WHERE ID=?"); 
    $query->bind_param('i', $itemID); 
    return @$query->execute() && $query->num_rows; 
}
That example doesn't really get in to OOP. Sure, there's message passing, but encapsulation, though present, isn't visible and there's nary a sign of polymorphism or inheritance. Add a "Store" class that represents the items stored in table Items and you're cooking.
 

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
I know it is not a prime example of OOP (classes, inheritance, ect) :p

It is just that you recoded it in a different way when you didn't need do, so thanks for it.

It is a problem with this new breed of teach-yourself kids learning programming that they can know PHP for years, then find out they didn't know the most basic things :)
 
Top