The Shopping Basket [ 168 ] 'subtotal' => ($data['product_price'] * $quantity ), 'weight' => $data['product_weight'], 'quantity' => $quantity, 'product' => $data['product_id'], 'basket' => $bid, 'name' => $data['product_name'] ); // return that all was successful return 'success'; } else { // error message return 'stock'; } } } else { // product does not exist: Error message return 'noproduct'; } } The controller In addition to the features discussed earlier, at this stage in the chapter, our controller needs to also: Detect if the customer is trying to add a product to the basket, that is, by clicking on an Add to basket button, and then processing this accordingly. Without this, products would never be added to a customer's basket. Pass data to the model to add a product to the basket. We need to tell the basket model which product the customer wants to add to their basket, so that it knows which product to associate with the current customer in the basket table. Display an error message if the product is not found, so the customer realizes the product has not been added to their basket and are not confused when they see their basket is missing the product. Display an error message if the product is out of stock, so the customer realizes the product has not been added to their basket, and are not confused when they see their basket is missing the product. • • • • 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 [ 169 ] If the product was found, and was in stock, it needs to display a conrmation message to the customer, so they know the product has been added to their basket. It should perhaps also redirect the customer to another page once the product was added successfully, such as the basket page, or the products page. Although this is quite a lot to do, the code for it is surprisingly simple: rst we have to extend the switch statement in the controller's constructor, so it can detect if theswitch statement in the controller's constructor, so it can detect if the statement in the controller's constructor, so it can detect if the customer is visiting the basket page. case 'add-product': echo $this->addProduct( $urlBits[2], 1); break; Then we have our addProduct function, which is called when the customer tries to add a product to the basket. This function tries to add a product to the basket model, and depending on the response displays appropriate messages to the customer. /** * Add product to the basket * @param String productPath the product reference * @param int $quantity the quantity of the product * @return String a message for the controller */ We check to see if the basket has already been checked, to save us from doing it again. We need to check the basket to determine if we are incrementing the quantity of a product in the basket, or adding a new product to the basket—so we already need to have our basket populated. public function addProduct( $productPath, $quantity=1 ) { // have we run the checkBasket method yet? if( ! $this->basket->isChecked == true ) { $this->basket->checkBasket(); } // We then call the addProduct method in the basket model and // make a note of the response it returns. $response = $this->basket->addProduct( $productPath, $quantity ); Depending on the response, the appropriate message is displayed to the customer. if( $response == 'success' ) { $this->registry->redirectUser('products/view/' . $productPath, 'Product added', 'The product has been added to your basket', false ); } elseif( $response == 'stock' ) { • 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 [ 170 ] $this->registry->getObject('template')-> buildFromTemplates('header.tpl.php', 'message.tpl.php', 'footer.tpl.php'); $this->registry->getObject('template')->getPage()-> addTag('header', 'Out of stock' ); $this->registry->getObject('template')->getPage()-> addTag('message', 'Sorry, that product is out of stock, and could not be added to your basket.' ); } elseif( $response == 'noproduct' ) { $this->registry->getObject('template')-> buildFromTemplates('header.tpl.php', 'message.tpl.php','footer.tpl.php'); $this->registry->getObject('template')->getPage()-> addTag('header', 'Product not found' ); $this->registry->getObject('template')->getPage()-> addTag('message', 'Sorry, that product was not found.' ); } } A note on etiquette When a customer adds products to their basket, it is important that only what they add to their basket is added. From personal experience, I know of a number of sites that try to auto-select other products, which then get added to your basket. It can be quite easy for a customer to miss this, and inadvertently purchase products they don't want. This will leave the customer unhappy, generate negative reviews about the site, and damage the store's reputation. Adding customizable products Earlier in this book, we discussed customizable products, which allowed customers to both upload les to associate with their product order, and to enter text related to a number of elds associated with their product order. To facilitate the purchase of such products, there are a number of things we need to do: Restructure the basket database Change how we view the shopping basket Change how we add a product to the basket Process the customized information, if the product was customizable • • • • 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 [ 171 ] Changing our basket database In our products table, we have two elds of interest, allow_upload and custom_text_inputs. In our basket table, we could benet from adding a eld to store the uploaded le and a eld to store the values from the custom text inputs. ALTER TABLE `basket_contents` ADD `uploaded_file` VARCHAR( 255 ) NOT NULL, ADD `custom_text_values` LONGTEXT NOT NULL Viewing the basket When viewing the basket, we may wish to display different information relating to the fact that a product has been customized. This involves changing our checkBasket method in the model, and also making some changes to the controller. The changes to the model need to detect if the basket entry has a le uploaded or a number of custom text submissions; if it does, then instead of adding it to the basket array with a prex of standard, we use a prex of customized. The reason for this prex is to ensure when the customer clicks on Add to basket a second time, we don't duplicate an existing product in the basket, but instead take into account the customizations that the customer made. Changing the model Changes required to our model are: Check to see if the product is customizable; if the product is customizable, then we need to process the request differently. Check to see if a le is being uploaded; if the product is customizable, and customers are permitted to upload les with their purchase (such as an image or photograph), the model needs to check if the customer has chosen to upload a le, so that it can process it. If the customer has chosen to upload a le, it needs to be uploaded to the server, and moved to a suitable location, such as the basket_uploads directory. The name and location of this le then needs to be stored in the basket_contents table. • • • 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 [ 172 ] Depending on the nature of the store, and the type of les we allow the customer to upload, we may also wish to store whether or not the le is an image. If the le is an image, we could display a thumbnail of this image on the customer's "basket view" page, so they can see the image they uploaded along with their product. If the product allows the customer to complete any custom text elds, we need to process these, and serialize the data, and store them in the database. The data needs to be serialized, so that the data from any number of elds (each product can store any variety of custom inputs) can be stored with their corresponding eld names, within one database eld. If the product is customizable, the product should be stored in the basket contents array with a prex of customizable This way the standard and customizable products can be handled differently as required. In addition to the prex and the product ID, we also need to store a unique reference, to indicate that the product is customized by means of the variations selected. This combined with the prex allows us to list each customization separately within the basket view. After all, the customer could purchase three t-shirts, but each of them of different sizes or with custom images uploaded with them. If this is the case, they should appear as three separate products listed in the basket. If they are all the same version, then they would only appear once, with a quantity of three. The controller In addition to the features discussed earlier, at this stage in the chapter, our controller now also needs to: Display custom text inputs when viewing basket contents, so that the customer can see which product in their basket has been customized in which way, enabling them to change quantities and remove specic customizations from their basket should they wish to. Display an uploaded image, if we wish, for the same reason as the previous one, but this would also make the basket more appealing to the customer. Display a link to download the le that has been uploaded by the customer allowing them to verify that they had in fact uploaded the correct le for their order, before proceeding. Adding product variants When it comes to adding products that have variations to our shopping basket, there are again a number of changes that need to be made to our current database and codebase. • • • • • • This material is copyright and is licensed for the sole use by jackie tracey on 23rd February 2010 953 Quincy Drive, , Brick, , 08724 . 2010 953 Quincy Drive, , Brick, , 08724 The Shopping Basket [ 170 ] $this->registry->getObject('template')-> buildFromTemplates('header.tpl .php& apos;, 'message.tpl .php& apos;,. $this->registry->getObject('template')-> buildFromTemplates('header.tpl .php& apos;, 'message.tpl .php& apos;,'footer.tpl .php& apos;); $this->registry->getObject('template')->getPage()->. values from the custom text inputs. ALTER TABLE `basket_contents` ADD `uploaded_file` VARCHAR( 255 ) NOT NULL, ADD `custom_text_values` LONGTEXT NOT NULL Viewing the basket When viewing the basket,