@Crinsane would you be open to a pull request changing private methods to protected? I wanted to extend the cart in my project to support items having a shipping weight, but some of the methods are private. Making them protected would be better I think, especially for a shared library like this.
I'd rather think about how to include shipping into the package to be honest. 馃槈
I can help with that as well, I have done some thinking on the subject and to me it seems like the best way is to just have shipping weight and maybe dimensions calculated by the cart (that's what I'm doing in my project). The weight/dimensions can then be passed to whatever API or code you are using to calculate shipping.
The part I am not sure about is how it should calculate the total. Right now there is a subtotal, which is the sum of each item multiplied with its quantity. And a total which includes the tax on each item. What do you suggest for the new total which would include shipping? Or maybe total does not even need to change, and once you determine the shipping cost you can calculate the new total yourself.
Yeah, the total is one problem, but also how to keep the basic API simple. I don't want to end up with for instance an add($id, $title, $qty, $price, $options, $tax, $shipping, $discount, ...) kind of method with 10+ parameters.
In my own project I tried to follow the way you did it with the Buyable interface which I think is nice and elegant and made a similar Shippable interface which has a getWeight() method. But I also understand that you don't want to force using the Buyable interface so there is also the option to pass in each parameter manually. If that is the case, perhaps we could switch to array style parameters so that the ordering and optional parameters are more flexible.
I'll give it some thoughts. I also prefer the Buyable way with interfaces actually.
When considering different approaches I think the main point is going to how much backwards compatibility you want to maintain and also how the cart should be used with and without the shipping feature.
Here is my extended cart class
<?php
namespace App\Services\Cart;
use Gloudemans\Shoppingcart\Cart as GloudemansCart;
use Gloudemans\Shoppingcart\CartItem;
class Cart extends GloudemansCart
{
public function weight()
{
$content = $this->getContent();
$weight = $content->reduce(function ($weight, CartItem $cartItem) {
return $weight + ($cartItem->model->getShippingWeight() * $cartItem->qty);
}, 0);
return $weight;
}
}
I have that along with an interface and trait similar to Buyable and CanBeBought and a service provider which just registers my extended class instead of the one from the package.
I have been doing some more thinking on the subject and my idea is that the cart can be thought of as having two types of logic.

Only after both are determined can we get the actual total.
@eberkund I haven't forgotten about this, just didn't had the time yet to really look into it.
So just wanted to let you know that I will get to it eventually :)
Okay great, let me know when you do and I will be happy to help.
I have been thinking on this some more and I think I have a good enough idea to begin working on the feature. I think the most flexible way of doing it would be to add two new concepts: "modifiers" and "extras".

It will work basically the same way it does now, you will be able to add items which get put into the cart's contents and you can pass in an optional $options array. However with this addition, you will be able to configure some custom modifier classes which will be run when the total is calculated or the extras are retrieved.
Since modifiers get run when the total or extras are calculated they will be able to modify the total or add items to the extras. You can think of extras as "computed items" based on the actual items that are in the cart. My idea is that you will be able to configure the class paths to your custom modifiers in config/cart.php.
An example of a modifier would be, ShippingModifier which would add up the weights (which is just a parameter of the associated model or something in the options array), calculate the cost, and add an extra to extras that says the shipping type. Then in your view you can display the cart contents and the cart extra (which includes, shipping, tax and total) underneath it.
I believe this method would be flexible to accommodate anything really like different tax rates, promo codes, free gift items, gift cards, etc.
Great ideas, any updates on making this happen?
I haven't had much time to work on this unfortunately. Another approach I came across is the one used by Stripe: https://stripe.com/docs/api#order_items
So, adapted for the shopping cart we would have cart items with similar types. What do people think of this approach?
Has this functionality been implemented? If yes, how would I use it? Cart :: extras ('shipping', $ valueOfShipping)?
have same issue i would like to add shipping charges like below
item = 50$
sub total = 100$
total 160$
Most helpful comment
I have been thinking on this some more and I think I have a good enough idea to begin working on the feature. I think the most flexible way of doing it would be to add two new concepts: "modifiers" and "extras".
It will work basically the same way it does now, you will be able to add items which get put into the cart's contents and you can pass in an optional
$optionsarray. However with this addition, you will be able to configure some custom modifier classes which will be run when the total is calculated or the extras are retrieved.Since modifiers get run when the total or extras are calculated they will be able to modify the total or add items to the extras. You can think of extras as "computed items" based on the actual items that are in the cart. My idea is that you will be able to configure the class paths to your custom modifiers in
config/cart.php.Examples
An example of a modifier would be,
ShippingModifierwhich would add up the weights (which is just a parameter of the associated model or something in the options array), calculate the cost, and add an extra to extras that says the shipping type. Then in your view you can display the cart contents and the cart extra (which includes, shipping, tax and total) underneath it.I believe this method would be flexible to accommodate anything really like different tax rates, promo codes, free gift items, gift cards, etc.