7 min read

Juniper Theatricals

Juniper Theatricals want to have a lot of products on their online store, and as a result they fear that some products may get lost within the website, or not be as obvious to their customers. To help prevent this problem, we will integrate product searching to make products easy to find, and we will add filters to product lists allowing customers to see products that match what they are looking for (for example, ones within their price range).

As some products could still be lost, they want to be able to recommend related products to customers when they view particular products. If a customer wants a product, and it happens to be out of stock, then they want to prevent the customer from purchasing it elsewhere; so we will look at stock notifications too.

The importance of user experience

Our customers’ experience on the stores powered by our framework is veryimportant. A good user experience will leave them feeling wanted and valued, whereas a poor user experience will leave them feeling unwanted, unvalued, and may leave a bad taste in their mouths.

Search

The ability for customers to be able to search, find, and filter products is vital, as if they cannot find what they are looking for they will be frustrated by our site and go somewhere where they can find what they are looking for much more easily.

There are two methods that can make it much easier for customers to find what they are looking for:

  • Keyword search: This method allows customers to search the product catalog based on a series of keywords.
  • Filtering: This method allows customers to filter down lists of products based on attributes, refining larger lists of products into ones that better match their requirements.

Finding products

The simplest way for us to implement a search feature is to search the product name and product description fields. To make the results more relevant, we can place different priorities on where matches were found; for instance, if a word or phrase is found in both the name and description then that would be of the highest importance; next would be products with the word or phrase in the name; and finally, we would have products that just have the word or phrase contained within the product description itself.

So, what is involved in adding search features to our framework? We need the following:

  • Search box: We need a search box for our customers to type in words or phrases.
  • Search feature in the controller: We need to add some code to search the products database for matching products.
  • Search results: Finally, we need to display the matching products to the customer.

Search box

We need a search box where our customers can type in words or phrases to search our stores. This should be a simple POST form pointing to the path products/search with a search field of product_search. The best place for this would be in our website’s header, so customers can perform their search from anywhere on the site or store.

<div id="search">
<form action="products/search" method="post">
<label for="product_search">Search for a product</label>
<input type="text" id="product_search" name="product_search" />
<input type="submit" id="search" name="search" value="Search" />
</form>
</div>

We now have a search box on the store:

PHP 5 E-commerce Development

Controlling searches with the products controller

A simple modification to our products controller will allow customers to search products. We need to make a small change to the constructor, to ensure that it knows when to deal with search requests. Then we need to create a search function to search products, store the results, and display them in a view.

Constructor changes

A simple switch statement can be used to detect if we are viewing a product, performing a search, or viewing all of the products in the database as a list.

$urlBits = $this->registry->getURLBits();
if( !isset( $urlBits[1] ) )
{
$this->listProducts();
}
else
{
switch( $urlBits[1] )
{
case 'view':
$this->viewProduct();
break;
case 'search':
$this->searchProducts();
break;
default:
$this->listProducts();
break;
}
}

This works by breaking down the URL and, depending on certain aspects of the URL, different methods are called from within the controller.

Search function

We now need a function to actually search our products database, such as the following:

private function searchProducts()
{
// check to see if the user has actually submitted the search form
if( isset( $_POST['product_search'] ) &&
$_POST['product_search'] != '' )
{

Assuming the customer has actually entered something to search, we need to clean the search phrase, so it is suitable to run in our database query, and then we perform the query. The phrase is checked against the name and description of the product, with the name taking priority within the results. The highlighted code illustrates the query with prioritization.

// clean up the search phrase
$searchPhrase = $this->registry->getObject('db')->
sanitizeData( $_POST['product_search'] );
$this->registry->getObject('template')->getPage()->
addTag( 'query', $_POST['product_search'] );
// perform the search, and cache the results, ready for the
// results template
$sql = "SELECT v.name, c.path,
IF(v.name LIKE '%{$searchPhrase}%', 0, 1) AS priority,
IF(v.content LIKE '%{$searchPhrase}%', 0, 1)
AS priorityb
FROM content c, content_versions v, content_types t
WHERE v.ID=c.current_revision AND c.type=t.ID
AND t.reference='product' AND c.active=1
AND ( v.name LIKE '%{$searchPhrase}%' OR v.content
LIKE '%{$searchPhrase}%' )
ORDER BY priority, priorityb ";
$cache = $this->registry->getObject('db')->cacheQuery( $sql );
if( $this->registry->getObject('db')->
numRowsFromCache( $cache ) == 0 )
{
// no results from the cached query, display the no results
// template
}

If there are some products matching the search, then we display the results to the customer.

else
{
// some results were found, display them on the results page
// IMPROVEMENT: paginated results
$this->registry->getObject('template')->getPage()->
addTag( 'results', array( 'SQL', $cache ) );
$this->registry->getObject('template')->
buildFromTemplates('header.tpl.php',
'products-searchresults.tpl.php', 'footer.tpl.php');
}
}
else
{
// search form not submitted, so just display the search box page
$this->registry->getObject('template')->
buildFromTemplates('header.tpl.php',
'products-searchform.tpl.php', 'footer.tpl.php');
}
}

As the results from the query are stored in a cache, we can simply assign this cache to a template tag variable, and the results will be displayed. Of course, as we need to account for the fact that there may be no results, we must check to ensure there are some results, and if there are none, we must display the relevant template.

Search results

Finally, we need a results page to display these results on.

<h2>Products found...</h2>
<p>The following products were found, matching your search for
{query}.</p>
<ul>
<!-- START results -->
<li><a href="products/view/{path}">{ name}</a></li>
<!-- END results -->
</ul>

Our search results page looks like this:

PHP 5 E-commerce Development

Improving searches

We could improve this search function by making it applicable for all types of content managed by the framework. Obviously if we were going to do this, it would need to be taken out of the products controller, perhaps either as a controller itself, or as a core registry function, or as part of the main content/pages controller.

The results could either be entirely in a main list, with a note of their type of content, or tabbed, with each type of content being displayed in a different tab. The following diagrams represent these potential Search Results pages.

PHP 5 E-commerce Development

 

And, of course, the tab-separated search results.

PHP 5 E-commerce Development

LEAVE A REPLY

Please enter your comment!
Please enter your name here