laravelshoppingcart icon indicating copy to clipboard operation
laravelshoppingcart copied to clipboard

Time to live for cart.

Open berpcor opened this issue 8 years ago • 16 comments

Hello. How can I set time to live for goods in my cart. In several hours cart becomes empty.

berpcor avatar Nov 24 '15 12:11 berpcor

Hello @berpcor, the cart does not have this functionality. But I believe you can do with your own implementation and just manually trigger the Cart::clear(); if the duration is met. This sounds interesting. Maybe you could elaborate more about your scenario and why you would need that. Pull requests are welcome. Thanks!

darryldecode avatar Nov 24 '15 13:11 darryldecode

I mean a bit different. I've added your package in my project, created cart functionality, added some goods in my cart. Then... I turned off my computer and gone to get some sleep. When I woke up (in something about 10 hours) I found that my cart is empty. How can I set time for goods to live in my cart?

berpcor avatar Nov 25 '15 20:11 berpcor

@berpcor The cart is stored in session, then if you turn off your computer, you lose the session and the cart. You should have a login procedure to bind a cart to a user and save the cart somewhere (e.g. a database table) to retrieve it during the next login.

SimoTod avatar Nov 28 '15 23:11 SimoTod

I have login procedure, of course. But my cart is not attached to any user (orders only). I think I am not the only who does like that (I know at least one big shop - aliexpress.com). So it would be a good idea to put session data to cookie and retrieve it from there. Moreover it would be good to have possibility to edit life time for cart.

berpcor avatar Nov 29 '15 02:11 berpcor

I don't think to this as a cart feature. This cart store data in laravel session, I took a look and it should be already persistent. Yesterday I was wrong: I think that you lost the session not because you closed the browser, but because the session was expired. You can set session lifetime and expire_on_close in laravel config file. This should do the job.

SimoTod avatar Nov 29 '15 12:11 SimoTod

"You can set session lifetime and expire_on_close in laravel config file." This is a good idea, but those settings will affect on any other sessions. Login session, for example. It is not very good idea to mix up settings. Why don't you think to this as a cart feature? We talk about life time of cart. So no matter how it realised, it is still cart feature. Why cookies? Because it is rather simple to set their life time independently. I suppose that it is not bad idea at all to store cart in cookies and to have possibility to define settings in dependence on your needs from the point of view of owner of online store. Are you agree?

berpcor avatar Nov 29 '15 12:11 berpcor

Yes, it seems reasonable to not mix up settings, but is not a trivial change. Currently storage politics is not made by the cart class. The service provider inject the session object and the cart call put/get on that. Honestly, i don't like to store the whole cart on a cookie, but it is a personal opinion (public pc issue, teens that edit directly the cookie :), etc). I like more a "cart bind to user" approach so I can find my cart on every device. But as I said before, it's a personal opinion, other user may have different needs, then I think it should be a functionalty built on top of the cart by the application.

SimoTod avatar Nov 29 '15 13:11 SimoTod

I am looking to use cookies as well for storing the cart contents. Reason is simple since I want the contents to persist across sessions so that its convenient for the user if they add a few items to thier wish list and come back a few days later and find it there!

I can see in the instances example that you can pass the storage driver to be used but I am unsure how I can use cookies instead of session. @darryldecode might advise if it's possible?

unitedworx avatar Feb 19 '16 20:02 unitedworx

Did you find a good way to solve your scenario? currently, the storage is hard-coded on the Cart's Service Provider which as you can see, we pull the laravel's session object $app['session'] and inject it as a storage of the cart items.

We can solve this maybe by changing it in a config like so:

public function register()
    {
        $this->app['cart'] = $this->app->share(function($app)
        {
            $storage = \Config::get('cart.storage') ? \Config::get('cart.storage') : $app['session'];
            $events = $app['events'];
            $instanceName = 'cart';
            $session_key = '4yTlTDKu3oJOfzD';
            return new Cart(
                $storage,
                $events,
                $instanceName,
                $session_key
            );
        });
}

What do you think?

darryldecode avatar Feb 22 '16 02:02 darryldecode

I might need to create another driver for cookies storage for this..

darryldecode avatar Feb 22 '16 02:02 darryldecode

@darryldecode As I understand operations that the driver needs to utilize are only put and get operations. So this can possibly be a simple class with 2 methods basicly doing a put and a get while utilising laravel cookie::get and cookie::set

Will give it a go since I need to use this on a project this week, will issue a push request to pull this in if a manage to work something

unitedworx avatar Feb 23 '16 18:02 unitedworx

Didn't realise that strorage driver was hard coded. Might be a good approach to load all $storage, $events, $instanceName and $session_key from a config file, if they are defined! so this is backwards compatible! Further you can expand this a little bit so that if more instances of the cart are needed you don't need to create a service provided to define but carts service provider can define them via the config filesince it can contain a nested array with both the default cart and any extra instances needed.

E.g a config structured this way

cart = array (
     $storage =
     $events = 
     $instanceName =
     $session_key =
     )
wishlist = array(
     $storage =
     $events = 
     $instanceName =
     $session_key =
     )

unitedworx avatar Feb 23 '16 19:02 unitedworx

I also need to set a longer life time to the cart session. Is there a clear solution for this?

tokayer avatar Sep 06 '16 12:09 tokayer

Hi, I need to set to time live too, Any update here, please ? Thank you.

malekbenelouafi avatar Aug 03 '18 23:08 malekbenelouafi

This is a cookie storage class with persistence of 14 days. Just make sure you are encrypting your cookies, because of unserialize. I think this should be added to readme.

// $this->app->singleton(CookieStorage::class);

class CookieStorage
{
    private $data = [];

    public function __construct()
    {
        $this->data = unserialize(Cookie::get('cart'), [
            'allowed_classes' => [
                CartCollection::class,
                ItemCollection::class,
                ItemAttributeCollection::class,
            ],
        ]) ?: [];
    }

    public function has($key)
    {
        return isset($this->data[$key]);
    }

    public function get($key)
    {
        return new CartCollection($this->data[$key] ?? []);
    }

    public function put($key, $value)
    {
        $this->data[$key] = $value;
        Cookie::queue(
            Cookie::make('cart', serialize($this->data), 60 * 24 * 14)
        );
    }
}

p.s. Cookies are not recommended, because cookie size is limited to 4kb which equals to 2-4 products in the cart of serialized objects. Solution could be to add support to serialize as JSON which would take less space.

AidasK avatar Jul 20 '19 18:07 AidasK

Well, that has a simple solution, on the cookie, only store an uuid, and then store the product in db within this uuid.

qlHelmann avatar Dec 11 '20 13:12 qlHelmann