Thursday 21 March 2013

Yii Framework Simple Shopping Cart Tutorial for Beginners

Provides shopping cart functionality for models. Cart is a container object that holds items collection and have handy methods to work with it. It uses user session as a cart data storage. 

INSTALLING AND CONFIGURING

1 way: Registration in the config file


Add to protected/config/main.php: 

'import'=>array(
    'ext.yiiext.components.shoppingCart.*'
),
 
'components' => array(
  'shoppingCart' =>
    array(
        'class' => 'ext.yiiext.components.shoppingCart.EShoppingCart',
    ),
 
)


2 way: Registration by necessity

$cart = Yii::createComponent(array(
    'class' => 'ext.yiiext.components.shoppingCart.EShoppingCart'
));
//Important!
$cart->init();
 
$book = Book::model()->findByPk(1);
 
$cart->put($book);


PREPARING A MODEL

Models that you are planning to put into the cart should implement IECartPosition interface: 

class Book extends CActiveRecord implements IECartPosition {
    public static function model($className = __CLASS__) {
        return parent::model($className);
    }
 
    function getId(){
        return 'Book'.$this->id;
    }
 
    function getPrice(){
        return $this->price;
    }
}


API

EShoppingCart::put($position, $quantity)



Adds $quantity items to the cart. If item is already in the cart, item data is being updated and item quantity is summed with $quantity. 

$book = Book::model()->findByPk(1);
Yii::app()->shoppingCart->put($book); //1 item with id=1, quantity=1.
Yii::app()->shoppingCart->put($book,2); //1 item with id=1, quantity=3.
$book2 = Book::model()->findByPk(2);
Yii::app()->shoppingCart->put($book2); //2 items with id=1 and id=2.
EShoppingCart::update($position, $quantity)



Updates cart item. If item is already in the cart, item data is being updated and item quantity is set to $quantity. If there is no such item yet it will be added. If $quantity<1 then item will be deleted. 

$book = Book::model()->findByPk(1);
Yii::app()->shoppingCart->put($book); //1 item with id=1, quantity=1.
Yii::app()->shoppingCart->update($book,2); //1 item with id=1, quantity=2.
EShoppingCart::remove($key)


Removes item from the cart. 

$book = Book::model()->findByPk(1);
Yii::app()->shoppingCart->put($book,2); //1 item with id=1, quantity=2.
Yii::app()->shoppingCart->remove($book->getId()); //no items
EShoppingCart::clear()
Clears all cart items.


Clears all cart items. 

Yii::app()->shoppingCart->clear();
EShoppingCart::itemAt($key)


Returns item at key $key. 

$position = Yii::app()->shoppingCart->itemAt(1);
EShoppingCart::contains($key)


Tells if cart contains item with id=$key. 

$position = Yii::app()->shoppingCart->itemAt();
EShoppingCart::isEmpty()


Tells if cart is empty. 

$position = Yii::app()->shoppingCart->isEmpty(1);
EShoppingCart::getCount()


Returns positions count. 

Yii::app()->shoppingCart->put($book,2);
Yii::app()->shoppingCart->put($book2,3);
Yii::app()->shoppingCart->getCount(); //2
EShoppingCart::getItemsCount()


Returns items count. 

Yii::app()->shoppingCart->put($book,2);
Yii::app()->shoppingCart->put($book2,3);
Yii::app()->shoppingCart->getItemsCount(); //5
EShoppingCart::getCost($withDiscount)


Returns cart total. 

Yii::app()->shoppingCart->put($book,2); //price=100
Yii::app()->shoppingCart->put($book2,1); //price=200
Yii::app()->shoppingCart->getCost(); //400
EShoppingCart::getPositions()


Returns an array with all positions. 

$positions = Yii::app()->shoppingCart->getPositions();
foreach($positions as $position) {
...
}
IECartPosition::getPrice()


Returns a price for a single item for this position. 

$positions = Yii::app()->shoppingCart->getPositions();
foreach($positions as $position) {
    $price = $position->getPrice();
}
IECartPosition::getSumPrice($withDiscount)


Returns position price = single item price*items count 

$book = Book::model()->findByPk(1); //price = 100
Yii::app()->shoppingCart->put($book,2); //putting 2 items
$positions = Yii::app()->shoppingCart->getPositions();
foreach($positions as $position) {
    $price = $position->getSumPrice(); //200 (2*100)
}
IECartPosition::getQuantity()


Returns position items quantity 

$book = Book::model()->findByPk(1); //price = 100
Yii::app()->shoppingCart->put($book,2); //putting 2 items
$positions = Yii::app()->shoppingCart->getPositions();
foreach($positions as $position) {
    $price = $position->getQuantity(); //2
}


DISCOUNTS


There is a single discount system built in. It allows to apply a set of rules that will change cart total or a single position price. Discount is a class that implements IEDiscount and defines apply() method that describes how exactly discount is applied. Discount is calculated by applying Position::addDiscountPrice/Position::setDiscountPrice position's method or EShoppingCart::addDiscountPrice/EShoppingCart::setDiscountPrice cart-wide method. This methods are getting one parameter that holds a value of cart total reduction or individual position reduction. Discount class example: 

class TestDiscount extends IEDiscount {
    /**
     * % discount
     */
    public $rate = 30;
 
    public function apply() {
        foreach ($this->shoppingCart as $position) {
            $quantity = $position->getQuantity();
            if ($quantity > 1) {
                $discountPrice = $this->rate * $position->getPrice() / 100;
                $position->addDiscountPrice($discountPrice);
            }
        }
    }
 
}


This example discount works like this: if there is more than one item for a single position, there will be $rate % discount for one item and it will be applied to position price. You can apply unlimited discount rules that will be called one by one: 

'shoppingCart' =>
    array(
        'class' => 'ext.yiiext.components.shoppingCart.EShoppingCart',
        'discounts' =>
        array(
            array(
                'class' => 'ext.yiiext.components.shoppingCart.discounts.TestDiscount',
                'rate' => 40),
            array('class' => 'otherDiscount'),
        ),
 
    ),



EVENTS

There are 2 events in ShoppingCart implemented in a standard Yii way: 
  1. onUpdatePosition - is triggered when position is added or updated. 
  2. onRemovePosition - is triggered when position is deleted.
Usage: 
$book = Book::model()->findByPk(1);
Yii::app()->shoppingCart[] = $book; //adding new position.
 
//iterating over all positions
foreach(Yii::app()->shoppingCart as $position)
{
...
 
}


When onUpdatePosition event is fired, call center will be notified. 
WORKING WITH A CART AS CMAP
ShoppingCart is a child of CMap so you can work with the cart as an array. 


No comments:

Yii Interview Question