2011-03-27 112 views
1

我的应用程序的规范指出,两个用户必须能够同时在Web应用程序的相同记录上工作,而不会破坏彼此的数据(除非他们每个修改相同的字段,那么它将是最后一个可以节省胜利。)这是一个医疗系统,可以想象的是,计费人员可以在记录的同时更新另一部分记录。何时应该清除会话变量?

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

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

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

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

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

那么,什么时候最好的时间和方法清理会话垃圾而不清除会话中实际需要的数据呢?

+0

只是一个说明 - 因为这是一个Web应用程序,而不是一个网站,我们的用户通常整天都在应用程序。所以,如果他们正在处理数十个记录,事情可能会变得非常疯狂。 – 2011-03-27 19:37:09

回答

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()方法工作不正常,但我会为你离开。确保在测试时(Session和Variables选项卡)使用DebugKit,并记住你需要刷新两次才能看到新的会话数据(因为在下一个请求之前PHP不能读取新的会话数据或类似的东西)。

+0

谢谢,我现在就玩这个。这是这样的东西,让我爱上了stackoverflow。 – 2011-03-29 18:14:40

0

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

0

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

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

我认为这是做到这一点的最好方法。

而且,这导致我最终的 问题。当用户保存表格 (如果 再次呈现相同的记录,则立即重新提取),我可以取消设置 会话中的数据。 但是,这并不处理 情况,当用户不保存 的形式。如果他们打开表格并且 读它然后走开,他们的会话将逐渐得到 碎片。

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

这种房子清洁的频率取决于你。我会将其设置为任何值,您认为这是一个人在特定表格上工作所需的最长时间+ 1分钟。

希望有帮助!

0

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