Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to shipping cost #36

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CartPositionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ interface CartPositionInterface
{
/** Triggered on cost calculation */
const EVENT_COST_CALCULATION = 'costCalculation';
/** Triggered on after cart shipping calculation */
const EVENT_SHIPPING_COST_CALCULATION = 'shippingCostcalculation';

/**
* @return integer
Expand All @@ -40,5 +42,5 @@ public function setQuantity($quantity);
/**
* @return int
*/
public function getQuantity();
public function getQuantity();
}
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,63 @@ $cart->on(ShoppingCart::EVENT_COST_CALCULATION, function ($event) {
$event->discountValue = 100;
});
```

5. During the calculation the following events are triggered:
- `ShoppingCart::EVENT_COST_CALCULATION` once per calculation.
- `CartPositionInterface::EVENT_COST_CALCULATION` for each position in the cart.

You can also subscribe on this events to perform discount calculation:

```php
$cart->on(ShoppingCart::EVENT_COST_CALCULATION, function ($event) {
$event->discountValue = 100;
});
```


Using shipping cost
---------------

Shipping costs are implemented as behaviors that could attached to the cart or it's positions. To use them, follow this steps:

1. Define discount class as a subclass of yz\shoppingcart\ShippingCostBehavior

```php
// app/components/FixedShippingCost.php

class FixedShippingCost extends ShippingCostBehavior
{
public $freeSince = 0;
public $ammount = 0;

/**
* @param ShippingCostCalculationEvent $event
*/
public function onShippingCostCalculation($event)
{
if($this->owner->getCost() < $this->freeSince)
$event->shippingValue = $this->ammount;
else
$event->shippingValue = 0;
}
}
```

2. Add this behavior to the cart:

```php
$cart->attachBehavior('fixedShippingCost', ['class' => 'app\components\FixedShippingCost', 'ammount' => 10, 'freeSince' => 999]);
```

3. To get shipping cost with discount applied:

```php
$cost = \Yii::$app->cart->getShippingCost(true);
```

4. To get cart total:

```php
$total = \Yii::$app->cart->getTotal(true);
```

28 changes: 28 additions & 0 deletions ShippingCostBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace yz\shoppingcart;

use yii\base\Behavior;


/**
* Class ShippingCostBehavior
* @package \yz\shoppingcart
*/
class ShippingCostBehavior extends Behavior
{
public function events()
{
return [
ShoppingCart::EVENT_SHIPPING_COST_CALCULATION => 'onShippingCostCalculation',
];
}

/**
* @param CostCalculationEvent $event
*/
public function onShippingCostCalculation($event)
{

}
}
20 changes: 20 additions & 0 deletions ShippingCostCalculationEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace yz\shoppingcart;

use yii\base\Event;


/**
* Class ShippingCostCalculationEvent
* @package \yz\shoppingcart
*/
class ShippingCostCalculationEvent extends Event
{
/**
* Shipping value that could be filled by the cart's behaviors that should provide shippings methods.
* This value will be added to the cart's cost
* @var float
*/
public $shippingValue = 0;
}
30 changes: 30 additions & 0 deletions ShoppingCart.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class ShoppingCart extends Component
const EVENT_CART_CHANGE = 'cartChange';
/** Triggered on after cart cost calculation */
const EVENT_COST_CALCULATION = 'costCalculation';
/** Triggered on after cart shipping calculation */
const EVENT_SHIPPING_COST_CALCULATION = 'shippingCostcalculation';

/**
* If true (default) cart will be automatically stored in and loaded from session.
Expand Down Expand Up @@ -278,6 +280,34 @@ public function getCost($withDiscount = false)
return $cost;
}

/**
* Return full cart shipping cost
* @param $withDiscount
* @return int
*/
public function getShippingCost($withDiscount = false)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why shipping cost must be in it's own separate method? It is possible to add shipping cost value during general computations using EVENT_COST_CALCULATION. If shipping cost should be based on the calculated cart cost, than probably it is possible to add event EVENT_AFTER_COST_CALCULATION and evaluate value of the cost there

Copy link
Author

@jjacquesf jjacquesf Jun 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I wrote two additional methods getShippingCost() and getTotal() in order to use something like this:
`
$cart = \Yii::$app->cart;

$cart->attachBehavior('percentDiscount', ['class' => 'common\components\PercentDiscount', 'ammount' => 10]);

$cart->attachBehavior('fixedShippingCost', ['class' => 'common\components\FixedShippingCost', 'ammount' => 89, 'freeSince' => 999]);

$subtotal = \Yii::$app->cart->getCost(true);

$shipping = \Yii::$app->cart->getShippingCost();

$total = \Yii::$app->cart->getTotal(true);
`

If there is a better way to get subtotal, shipping cost and total independently?

{
$cost = $this->getCost($withDiscount);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value is not used

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. I delete that line.


$shippingCostEvent = new ShippingCostCalculationEvent([]);
$this->trigger(self::EVENT_SHIPPING_COST_CALCULATION, $shippingCostEvent);
$cost = $shippingCostEvent->shippingValue;
return $cost;
}

/**
* Return full cart total cost
* @param $withDiscount
* @return int
*/
public function getTotal($withDiscount = false)
{
$cost = $this->getCost($withDiscount);
$shipping = $this->getShippingCost($withDiscount);

return $cost + $shipping;
}

/**
* Returns hash (md5) of the current cart, that is unique to the current combination
* of positions, quantities and costs. This helps us fast compare if two carts are the same, or not, also
Expand Down