Chapter 6 [ 163 ] { // they are logged in, get their ID $u = $this->registry->getObject('authentication')->getUserID(); The checkBasket() function runs one of two queries to lookup products in the basket: one if the customer is logged in, which checks for products based off the customer's ID, and another if they are not logged in, which uses the IP address and session ID to determine which products are from the current customer's basket. $sql = "SELECT b.ID AS basket_id, b.quantity AS product_quantity, c.ID AS product_id, v.name AS product_name, p.stock AS product_stock, p.weight AS product_weight, p.price AS product_price, p.SKU AS product_sku FROM content_versions v, content c, content_types t, content_types_products p, basket_contents b WHERE c.active=1 AND c.secure=0 AND c.type=t.ID AND t.reference='product' AND p.content_version=v.ID AND v.ID=c.current_revision AND c.ID=b.product_id AND b.user_id={$u}"; } else { $sql = "SELECT b.ID AS basket_id, b.quantity AS product_quantity, c.ID AS product_id, v.name AS product_name, p.stock AS product_stock, p.weight AS product_weight, p.price AS product_price, p.SKU AS product_sku, FROM content_versions v, content c, content_types t, content_types_products p, basket_contents b WHERE c.active=1 AND c.secure=0 AND c.type=t.ID AND t.reference='product' AND p.content_version=v.ID AND v.ID=c.current_revision AND c.ID=b.product_id AND b.user_id=0 AND b.session_id='{$session_id}' AND b.ip_address='{$ip_address}'"; } // do the query $this->registry->getObject('db')->executeQuery( $sql ); This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Download at Wow! eBook The Shopping Basket [ 164 ] If the query yielded results, we indicate that the basket isn't empty, and then iterate through the results, building our basket. We will need to modify this later to handle customizable products. if( $this->registry->getObject('db')->numRows() > 0 ) { // we have some products in our basket // set the relevant variable $this->basketEmpty = false; while( $contents = $this->registry->getObject('db')->getRows() ) { // for each product, add them to the basket object $this->contents[ 'standard-' . $contents['product_id'] ] = array( 'unitcost' => $contents['product_price'], 'subtotal' => ($contents['product_price'] * $contents['product_quantity']), 'weight' => $contents['product_weight'], 'quantity' => $contents['product_quantity'], 'product' => $contents['product_id'], 'basket' => $contents['basket_id'], 'name' => $contents['product_name'] ); $this->numProducts = $this->numItems + $contents['quantity']; $this->cost = $this->cost + ( $contents['price'] * $contents['quantity'] ); } } } The controller At this stage in the chapter, our controller needs to: Detect if the customer is trying to view the basket Get the basket contents from the model Cache basket contents and associate them with a template tag The following code does this, as described within: public function viewBasket() { // Build the view from the appropriate template $this->registry->getObject('template')-> buildFromTemplates('header.tpl.php', 'viewbasket.tpl.php', 'footer.tpl.php'); • • • This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Chapter 6 [ 165 ] Get the contents of the basket from the basket model, and build it into an array suitable for caching and sending to the template engine. $contents = $this->basket->getContents(); $products = array(); foreach( $contents as $reference => $data ) { $data['basket_id'] = $data['basket']; $data['basket'] = ''; $products[] = $data; } // Send the basket data to the template engine, and assign other // information such as total cost and number of products to // template variables. $basketCache = $this->registry->getObject('db')->c acheData( $products ); $this->registry->getObject('template')->getPage()-> addTag( 'products', array( 'DATA', $basketCache ) ); $this->registry->getObject('template')->getPage()-> addTag( 'basket_total', $this->basket->getTotal() ); } Adding products Adding a standard product to the basket should be straightforward; we only need to record the product's ID number and information of the user (such as their user ID or if they are not a logged-in user, some session data). As our basket will be maintained as an array, with product IDs acting as the keys, and other data such as price, name, quantity, and so on, acting as the elements, we should prex the ID to ensure we don't have problems with adding product variants or customizable products to our basket later on. For example, if a product can have an image uploaded, and we add two of these products with different images, we don't want the basket treating this as one product, but with a quantity of two. However, with a product that can't be customized, this is exactly what we do want! Let's start with the functionality for adding a standard product to our shopping basket. An addProduct method When a customer clicks on the Add to basket button on our store, what do we need to do? 1. First, we need to check that the product is valid and active, after all we can't add a product that does not exist to a user's shopping basket. This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 The Shopping Basket [ 166 ] 2. Secondly, we need to check that it is not a customizable product, or product that has variations (as this function will just deal with standard products for the time being). 3. Finally, we check to see if the product is already in the basket—if it is, then we increment the product's quantity in the basket; if it isn't, then we add it to the basket. The following code represents a suitable addProduct method. Although quantity is a parameter for the method, in most instances, we would want this to default to one, as when a customer clicks on Add to basket they would only want one added to the basket. /** * Add product to the basket * @param String productPath the product referenceString productPath the product reference productPath the product reference * @param int $quantity the quantity of the product * @return String a message for the controller */ public function addProduct( $productPath, $quantity=1 ) { // have we run the checkBasket method yet? if( ! $this->basketChecked == true ) { $this->checkBasket(); } // check the product exists $productQuery = "SELECT v.name AS product_name, c.ID AS product_id, p.allow_upload AS allow_upload, p.stock AS product_stock, p.weight AS product_weight, p.price AS product_price, p.SKU AS product_sku, p.featured AS product_featured, v.heading AS product_heading, v.content AS product_description, v.metakeywords AS metakeywords, v.metarobots AS metarobots, v.metadescription AS metadescription FROM content_versions v, content c, content_types t, content_types_products p WHERE c.active=1 AND c.secure=0 AND c.type=t.ID AND t.reference='product' AND p.content_version=v.ID AND v.ID=c.current_revision AND c.path='{$productPath}'"; $this->registry->getObject('db')->executeQuery( $productQuery ); if( $this->registry->getObject('db')->numRows() == 1 ) { // get the ID, etc $data = $this->registry->getObject('db')->getRows(); This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Chapter 6 [ 167 ] // check if it already in the basket if( array_key_exists( 'standard-' . $data['product_id'], $this->contents ) == true ) { // check stock if( $data['product_stock'] == -1 || $data['product_stock'] >= ( $this->contents['standard-' . $data['product_id']]['quantity'] + $quantity ) ) { // increment the quantity $this->contents['standard-' . $data['product_id']]['quantity'] = $this->contents['standard-' . $data['product_id']]['quantity']+$quantity; // update the database $this->registry->getObject('db')-> updateRecords('basket_contents', array('quantity'=> $this->contents[ 'standard-' . $product]['quantity'] ), 'ID = ' . $this->contents['standard-'.$product]['basket'] ); return 'success'; } else { // error message return 'stock'; } } else { if( $data['product_stock'] == -1 || $data['product_stock'] >= $quantity ) { // add product // insert the new listing into the basket $s = session_id(); $u = ( $this->registry->getObject('authentication')-> isLoggedIn() ) ? $this->registry-> getObject('authentication')->getUserID() : 0; $ip = $_SERVER['REMOTE_ADDR']; $item = array( 'session_id' => $s, 'user_id' => $u, 'product_id' => $data['product_id'], 'quantity' => $quantity, 'ip_address' => $ip ); $this->registry->getObject('db')-> insertRecords( 'basket_contents', $item ); $bid = $this->registry->getObject('db')->lastInsertID(); // add the product to the contents array $this->contents['standard-' . $data['product_id'] ] = array( 'unitcost' => $data['product_price'], This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 . buildFromTemplates('header.tpl .php& apos;, 'viewbasket.tpl .php& apos;, 'footer.tpl .php& apos;); • • • This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy. material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Download at Wow! eBook The Shopping Basket [ 164 ] If the query. sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 Chapter 6 [ 1 65 ] Get the contents of the basket from the basket model, and build it into an array suitable for