Improving the wish list There are a number of ways in which we could improve the wish-list feature we have added to our framework, including: Multiple lists per customer, allowing custom
Trang 1Gift purchases
The complication of gift purchases is that the purchases need to be stored with the
delivery address from the customer who created the wish list The difficulty here is
that, at any stage, the delivery address should not be presented to the user making
the purchase, as this is private information
Self purchases
Self purchases should be very straightforward to handle Essentially, all the customer
would be doing is adding their own wish-list product to their own shopping basket,
the only difference being that we must maintain a record that this is from their
wish list up until the point of their order being finalized; then we must remove
the product from their wish-list completely, to prevent them from making a
duplicate purchase
Improving the wish list
There are a number of ways in which we could improve the wish-list feature we
have added to our framework, including:
Multiple lists per customer, allowing customers to maintain separate lists
Garbage collection for session-based wish-list products, ensuring we don't
have useless data in our database
Transferring of session-based wish-list products to user account-based
wish-list products when a user is logged in
Model, as we didn't implement a model with this wish list, and we should do
so to make it easier to extend
Priority isn't considered or displayed to the customer, or anyone who would
like to buy the product as a gift for someone
Quantities, at present, they are not considered when adding a product to
a list; perhaps we should look for existing products in the wish list and
increment their quantity
Public and private lists, allowing customers to have a private list, and also a
public list of items they may wish for others to purchase for them
These improvements are ones you should investigate
by adding yourself
•
•
•
•
•
•
•
Trang 2Sometimes, we may find that certain products go hand in hand, or that customers
interested in certain products also find another group of products interesting or
relevant If we can suggest some relevant products to our customers, we increase the
chances of them making a new purchase or adding something else to their shopping
basket There are two methods of recommendation that we should look into:
Displaying related products on a products page
E-mailing customers who have made certain purchases to inform them of
some other products they may be interested in
Related products
The simplest way to inform customers of related products from within the product
view is to maintain a relationship of related products within the database and
within the products model, so we could cache the result of a subset of these related
products This way, the controller needs to only detect that there are more than zero
related products, insert the relevant template bit into the view, and then associate the
cached query as the template tag variable to ensure that they are displayed
There are a few ways in which we can maintain this relationship of related products:
Within the products table we maintain a serialized array of related
product IDs
We group related products together by themes
We relate pairs of related products together
A serialized array isn't the most effective way to store related product data Relating
them by themes would prove problematic with multiple themes, and also when it
comes to the administrator relating products to each other, as they would have to
select or create a new theme Relating pairs of products together would require a
little trick with the query to get the product name, as the ID of the product being
viewed could be one of two fields, as illustrated by the following table structure:
ID (Integer, Primary Key, Auto Increment)
ProductA (Integer)
ProductB (Integer)
•
•
•
•
•
•
•
•
Trang 3The difference between using productA or productB to store a particular product
reference would be determined by the administration panel we develop So if we
were to view and edit a product in the administration panel, and we chose to set a
related product, the product we were currently viewing would be productA and the
related one, productB
The SQL for this table structure is as follows:
CREATE TABLE `product_relevant_products` (
`ID` int(11) NOT NULL auto_increment,
`productA` int(11) NOT NULL,
`productB` int(11) NOT NULL,
PRIMARY KEY (`ID`),
KEY `productB` (`productB`),
KEY `productA` (`productA`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
ALTER TABLE `product_relevant_products`
ADD CONSTRAINT `product_relevant_products_ibfk_2`
FOREIGN KEY (`productB`) REFERENCES `content` (`ID`)
ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `product_relevant_products_ibfk_1`
FOREIGN KEY (`productA`) REFERENCES `content` (`ID`)
ON DELETE CASCADE ON UPDATE CASCADE;
We can get round the issue of the fact that the current product ID could be found
in both the productA and productB columns in the database with an IF statement
within our query The IF statement would work by checking to see if productA is
the product the customer is viewing; if it is, then the name of productB is returned;
otherwise, the name of productB is returned This gives us a query such as the
following, where CURRENT_PRODUCT_ID is the ID of the product the customer is
currently viewing
SELECT IF(rp.productA<>CURRENT_PRODUCT_ID,v.name,vn.name)
AS product_name,
IF(rp.productA<>CURRENT_PRODUCT_ID,c.path,cn.path)
AS product_path, rp.productA, rp.productB,
c.path AS cpath, cn.path AS cnpath, c.ID AS cid,
cn.ID AS cnid
FROM content c, content cn, product_relevant_products rp,
content_versions v, content_versions vn
WHERE (rp.productA= CURRENT_PRODUCT_ID
OR rp.productB= CURRENT_PRODUCT_ID)
AND c.ID=rp.productA AND cn.ID=rp.productB
AND v.ID=c.current_revision AND vn.ID=cn.current_revision
Trang 4As we may have a lot of related products, we may wish to put a limit on the number
of related products displayed, and randomize the results
SELECT IF(rp.productA<>CURRENT_PRODUCT_ID,v.name,vn.name)
AS product_name,
IF(rp.productA<>CURRENT_PRODUCT_ID,c.path,cn.path)
AS product_path, rp.productA, rp.productB,
c.path AS cpath, cn.path AS cnpath, c.ID AS cid,
cn.ID AS cnid
FROM content c, content cn, product_relevant_products rp,
content_versions v, content_versions vn
WHERE (rp.productA= CURRENT_PRODUCT_ID
OR rp.productB= CURRENT_PRODUCT_ID) AND c.ID=rp.productA
AND cn.ID=rp.productB AND v.ID=c.current_revision
AND vn.ID=cn.current_revision
ORDER BY RAND() LIMIT 5
Controlling the related products
If we create a new function within our controller to run our random related products
query, cache the result, and associate the cached results with a template variable,
all we would need to do is call this function from within the product view function,
passing the product ID as the parameter
private function relatedProducts( $currentProduct )
{
$relatedProductsSQL = "SELECT ".
" IF(rp.productA<>{$currentProduct},v.name,vn.name)
AS product_name,
IF(rp.productA<>{$currentProduct},c.path,cn.path)
AS product_path, rp.productA, rp.productB, c.path as cpath,
cn.path AS cnpath, c.ID AS cid, cn.ID AS cnid ".
" FROM ".
" content c, content cn, product_relevant_products rp,
content_versions v, content_versions vn".
" WHERE ".
" (rp.productA={$currentProduct}
OR rp.productB={$currentProduct}) ".
" AND c.ID=rp.productA ".
" AND cn.ID=rp.productB ".
" AND v.ID=c.current_revision ".
" AND vn.ID=cn.current_revision ".
" ORDER BY RAND() ".
" LIMIT 5";
$relatedProductsCache = $this->registry->getObject('db')->
cacheQuery( $relatedProductsSQL );
$this->registry->getObject('template')->getPage()->
addTag('relatedproducts', array( 'SQL', $relatedProductsCache ));
Trang 5The following line calls our new function:
$this->relatedProducts( $productData['ID'] );
Viewing the related products
Related products are now cached and associated with a template variable We
now need to add relevant mark up into our view product template, to display
related products
<h2>Related products</h2>
<! START relatedproducts >
<div class="floatingbox">
<a href="products/view/{product_path}">{product_name}</a>
</div>
<! END relatedproducts >
Of course, we can style this to however we wish: we could display them as small
boxes alongside each other, or we could also use JavaScript to toggle between them
However, for now, a simple list or floating <div> should suffice
Here, beneath the product details, we have a list of related products:
E-mail recommendations
There is only so much we can do for this feature at the moment, as it requires our
customers to have made some purchases, and at the moment, we don't have the
functionality available for customers to make a purchase However, we can discuss
what would be involved in creating this feature: