Php 尝试从Laravel 5.2中的排队作业访问会话数据

Php 尝试从Laravel 5.2中的排队作业访问会话数据,php,laravel,laravel-5.2,Php,Laravel,Laravel 5.2,我正在开发一个网络应用程序,允许人们与老师一起预订时间。目前的情况是,一旦时间添加到用户购物车中,其他人就看不到该时间可用,也无法将其添加到他们的购物车中 只要会话持续(2小时),我将使用存储项目的模式。但是,我想项目被自动删除后5分钟被添加。为了实现这一点,我设置了一个延迟5分钟的排队作业 我的问题是,作业会更改时间,使其在5分钟后再次对其他用户可见,但不会将其从购物车中删除,因为它似乎无法访问存储购物车数据的会话。有人能建议我如何从排队作业访问存储在会话中的购物车数据吗? 谢谢 这是该作业的

我正在开发一个网络应用程序,允许人们与老师一起预订时间。目前的情况是,一旦时间添加到用户购物车中,其他人就看不到该时间可用,也无法将其添加到他们的购物车中

只要会话持续(2小时),我将使用存储项目的模式。但是,我想项目被自动删除后5分钟被添加。为了实现这一点,我设置了一个延迟5分钟的排队作业

我的问题是,作业会更改时间,使其在5分钟后再次对其他用户可见,但不会将其从购物车中删除,因为它似乎无法访问存储购物车数据的会话。有人能建议我如何从排队作业访问存储在会话中的购物车数据吗? 谢谢

这是该作业的代码,除了Cart::remove()之外,其他一切都可以正常工作


Cron作业在新会话中运行。您的购物车库(DarryDecode/laravelshoppingcart)基于会话。如果不是从当前用户的浏览器启动的会话更改会话数据(可能不可能?取决于您的会话驱动程序),则将非常困难。具体而言,这一行:

Cart::remove($timeSlot->id);
购物车模型无法知道从哪个购物车中删除项目。从用户体验的角度来看——你要给用户一些反馈,告诉他们他们的时间段已经被删除了;因此,在每个页面绘图(或通过js异步)上编写删除检查不应该是意外的工作

在每个页面上绘制,循环浏览访客购物车中的每个项目。我不知道您是如何构造cart::add(…)来处理唯一的购物车项目id的,因此这假设时间段id与购物车项目id匹配

$removed = [];
foreach(Cart::getContent() as $item) {
    $timeSlot = timeSlot::findOrFail($item->id);
    if( $timeSlot->in_basket === 0 ) {
        Cart::remove($timeSlot->id);
    }
}
if(count($removed)) {
    //inject a HTML/JS popup message like "your timeslot has been dropped because you're too slow
    //or pass it along into the request
    $request->session()->flash('slots-dropped', $removed);
}
这在cartUpdate中间件中得到了理想的处理,但也可以在控制器中完成,具体取决于站点的复杂性

[编辑] 由于数据库结构的原因,上述解决方案中存在一个缺陷-用户a保留了一个时间段,但未在签出窗口内签出,该时间段在用户a注意到之前几分钟内返回到“不在购物车”状态;同时,用户B在返回到可用时隙池之后,在用户A查看另一个页面之前(并且购物车使用适当的消息更新),会看到相同的时隙。此时,时间段位于人员B的购物车中。当页面刷新查看人员A的时间段是否在“任何”购物车中时,它会说“是的,它在购物车中,因为$timeslot->in_basket==1”。人员A继续签出并获得时间段,即使其位于人员B的购物车中

对此的修复相当简单-将in_basket的数据类型从布尔值更改为字符串,并在每次将其添加到购物车时为其分配会话id的值。从cart类中可以看到,这可能是app()->session->get('session')。在整个过程中进行重构之前,您可以使用var_dump(app()->session->all())来查看这是否正确。更新后的解决方案将如下所示:

$removed = [];
foreach(Cart::getContent() as $item) {
    $timeSlot = timeSlot::findOrFail($item->id);
    if( $timeSlot->in_basket !== app()->session->get('session') ) {
        Cart::remove($timeSlot->id);
    }
}
if(count($removed)) {
    //inject a HTML/JS popup message like "your timeslot has been dropped because you're too slow
    //or pass it along into the request
    $request->session()->flash('slots-dropped', $removed);
}

在你把它们扔掉之前,你会想得到一个开放预订的列表,这样你就可以把它们从购物车中释放出来。这一切都需要由你的排队作业来处理-你能分享一下你目前是如何从数据库中清除它们的吗?对不起,我不确定你所说的“开放预订”到底是什么意思。当前,将时间添加到购物车时,它的“in_cart”值在数据库中设置为1,然后排队作业在5分钟后自动将其设置为0。问题是我无法从作业中使用购物车外观,因为作业似乎无法访问它。也许可以,我做错了什么?你能分享你工作的代码吗?添加到最初的帖子中,谢谢。谢谢!你的回答很有帮助,我真的很感谢你花时间来写它。这是一个伟大的解决方案,用户留在网站上。对于用户在购物车中添加内容,然后立即离开网站的情况,您有何建议?我应该让会话在5分钟后过期吗?如果他们离开了站点,他们的会话应该使用自然会话过期-同样,这取决于您使用的会话驱动程序,但通常默认为两小时,并且购物车将从内存中消失。如果有人离开你的网站,并在两小时内返回-他们可能仍然希望有一个购物车与他们的时间仍然在它。。。因此,向他们展示一条相反的信息将是一个很好的用户体验实践。您不必以任何不同的方式来处理这种情况——它遵循相同的逻辑:在每个页面绘制上,检查会话/购物车是否存在,如果时间段无效,则更新购物车。
$removed = [];
foreach(Cart::getContent() as $item) {
    $timeSlot = timeSlot::findOrFail($item->id);
    if( $timeSlot->in_basket !== app()->session->get('session') ) {
        Cart::remove($timeSlot->id);
    }
}
if(count($removed)) {
    //inject a HTML/JS popup message like "your timeslot has been dropped because you're too slow
    //or pass it along into the request
    $request->session()->flash('slots-dropped', $removed);
}