$contents['product_id'] ] = array 'unitcost' => $contents['product_price'], 'subtotal' => $contents['product_price'] * $contents['product_quantity'], 'weight' => $contents['product_w
Trang 1{
// 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 );
Trang 2If 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');
•
•
•
Trang 3Get 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 prefix 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.
Trang 42 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 reference String 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();
Trang 5// 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'],