我有一个自己构建的购物车,它使用会话变量来维护请求中的购物车状态。我有一个递增和递减按钮,允许用户增加或减少购物车中的产品数量。这是通过Ajax请求发生的。推车类通过在构造时将推车恢复到会话之外进行操作,并在销毁时将推车保存回会话。
<?php
class Cart {
/**
* constructor
*/
public function __construct(){
//restore cart
$this->restore();
}
/**
* destructor
*/
public function __destruct(){
//save cart
$this->save();
}
/**
* restore
*/
public function restore(){
//retrieve session info
if(Session::has('cart')){
//get cart
$session = Session::get('cart');
//assign session info
$this->data = ($session['data']);
$this->rates = $session['rates'];
$this->lines = $session['lines'];
}
}
/**
* save
*/
public function save(){
Session::put('cart', $this->forSession());
}
我遇到的问题是具有多个Ajax请求的竞争条件。用户可以多次点击按钮,发送多个Ajax请求。因此,每个请求都会拉出会话的当前状态,执行操作,然后保存它。问题是以前的交易未必在restore
购物车时完成并保存。我的第一个修复是让任何后续的Ajax请求取消前一个请求,以减少不必要的(立即覆盖的)请求,并帮助避免这种竞争条件。虽然它似乎有所帮助,但它仍然是古怪的。所以我的下一个想法是在源头攻击它,即购物车类本身。我的想法是实现某种类型的锁定&#39;防止在前一次操作完成之前访问购物车。这个想法看起来像这样。
<?php
/**
* is cart locked
*/
public function isCartLocked(){
if(Session::get('cartLock') === 1){
sleep(1);
$this->isCartLocked();
}
}
public function restore(){
Session::put('cartLock', 0);
//check if cart is locked
$this->isCartLocked();
//lock cart
Session::put('cartLock', 1);
...
}
public function save(){
//unlock the cart
Session::put('cartLock', 0);
...
}
现在第一个问题是,我应该做这样的事情,锁定?然后,如果是这样,这是一个处理它的好方法吗?
在我第一次尝试之后,我似乎遇到的问题是析构函数不一定被调用,这导致我的购物车保持锁定状态,并最终导致超时错误。
感谢您的帮助!
答案 0 :(得分:1)
我认为你实际上想要去掉对AJAX请求的函数调用,这样你就不用担心自己锁定/解锁或取消之前的请求 - 只要你相对确定它们就做一个完成了调整数量。
我建议使用this jQuery plugin来限制或去除JavaScript函数调用(虽然jQuery实际上并不需要使用它,如果可用的话,它只能通过jQuery命名空间访问),假设你是如何制作你的AJAX的请求。
答案 1 :(得分:0)
我不得不说,如果你遇到了竞争条件,那么你在应用程序设计方面遇到了一些问题,这些问题可能会困扰你的应用程序一段时间,因为会话的并发访问会粉碎你的会话商店相对频繁
在我看来,最简单的方法是使用数据库表,而不是更新字段,而是为每个用户事件添加一行(因此,将插入增量操作,1,并且减量会插入一行-1)
通过这种方式,您只需执行总和操作即可统计您的计数,当用户结帐流程完成后,您可以清理购物车表中的整个订单。