应该何时清除会话变量?

时间:2011-03-27 19:27:40

标签: php session cakephp

我的应用程序的规范声明两个用户必须能够同时处理Web应用程序的同一记录而不会破坏彼此的数据(当然,除非他们每个都修改相同的字段,否则它将是保存胜利的最后一个。)这是一个医疗系统,可以想象,当技术人员正在更新记录的另一部分时,计费人员可能正在处理记录。

因此,当用户保存表单时,系统应该只更改用户实际更改的数据库中的值。因为我正在使用CakePHP,所以我试图在PHP方面处理这个问题,而不是在发送表单数据之前使用JavaScript。

我的第一个想法是在保存之前立即检查数据库中的值,并仅更改不相同的值。但是,如果用户A在用户B打开表单后保存表单,然后用户B保存表单,则用户A的更改将被用户B表单中的旧数据覆盖。

我的下一个想法是在用户的会话中保存表单的值。因此,当他打开表单时,数据将存储在会话中,并且只有在其会话中更改的值才会在数据库中更新。因此,Session会将$ old_data序列化。

这里的问题是,如果用户尝试同时打开两个记录然后保存,则会导致悲伤。所以,我需要通过记录ID存储会话数据。

而且,这引出了我最后的问题。当用户保存表单时,我可以取消设置会话中的数据(如果再次呈现相同的记录,则立即重新获取它)。但是,这并不涉及用户不保存表单时的情况。如果他们打开表格并阅读然后离开,他们的会话就会逐渐充满碎片。

那么,何时是清理会话垃圾的最佳时间和方法,而不会消除会话中实际需要的数据?

4 个答案:

答案 0 :(得分:1)

今天下午我接受了一些挑战,所以试试这个 - 主要是看看是否所有逻辑都可以封装到一个组件中,而不必手动调用控制器动作的代码。

生成的SaveDiff component尚未在生产中使用,因此需要进行一些测试。 (如果发现任何错误,请随意在GitHub上进行更改。)

<?php
class ModelsController extends AppController {

    public $components = array(
        'SaveDiff' => array( # include the component
            'actions' => array('edit'), # tell it which actions to work with
        ),
    );

    public function edit($id) {
        $record = $this->read(null, $id)
        # not found
        if (!$record) {
            $this->cakeError('error404');
        }
        # populate form
        if (!$this->data) {
            $this->data = $record;
            return;
        }
        # save form
        $saved = $this->Model->save($this->data);
        if (!$saved) {
            $this->Session->setFlash('Failed validation');
            return;
        }
        # success
        $this->Session->setFlash('Saved changed fields');
        $this->redirect(array('action' => 'index'));
    }
}

在控制器操作期间(上例中为ModelsController::edit()),使用$this->data填充表单。控制器操作呈现后,组件将触发,并将$this->data保存到会话中。好吧,除非验证失败,因为我们可能在那时处理用户提交的数据。

当新的请求进入组件时,在控制器操作之前再次触发,并清除$this->data之外的任何未更改的数据(通过将其与会话进行比较),这意味着它应该满足您的要求(仅限更改的字段)并准备好保存。

注意:我注意到我的SaveDiffComponent::extractChanges()方法工作不正常,但我会留给你。确保在测试时使用DebugKit(会话和变量选项卡),并记住需要刷新两次以查看新的会话数据(因为PHP在下一个请求之前无法读取新的会话数据......或类似的东西)。

答案 1 :(得分:0)

您可以将每个项目放在会话数据中,每个记录都是自己的数组。 又名 $_SESSION["client1"]将是第一个客户的信息,而$_SESSION["client2"]将是第二个客户的信息。

答案 2 :(得分:0)

感谢您概述您的思考过程。

  

我的下一个想法是保存价值观   用户会话中的表单。所以,   当他打开表格时,数据就会得到   存储在会话中,只有   已经改变的价值观   在他的会议将得到更新   数据库。所以,会议会有   序列化了$ old_data。

我认为这是最好的方法。

  

而且,这导致我进入决赛   问题。我可以取消来自的数据   用户保存表单时的会话   (如果是,请立即重新获取它   他们再次渲染相同的记录)。   但是,这并没有涉及到   用户不保存的情况   表格。如果他们打开表格并且   读它然后逐渐消失   他们的会议将充满了   碎屑。

请记住,会话最终会过期。那时,旧的会话数据将被删除。如果这对您来说太长,您可以在会话数据中添加日期时间,并在加载页面时循环访问会话数据以删除过期信息。

此房屋清洁的频率取决于您。我会把它设置为你认为是一个人在特定表格上工作的最长时间+ 1分钟。

希望有所帮助!

答案 3 :(得分:0)

我不确定你的系统的设计,但正如你提到的这是一个医疗系统,表格中是否有某种修订标识符?如果是这样,你可以有一个隐藏的字段来跟踪两个用户的起点,然后仍然可以与已经改变的内容进行比较而不需要在会话对象中拉得那么多。