How to easily implement (faux) multi-user record locking

A place for users and developers of the Xataface to discuss and receive support.

How to easily implement (faux) multi-user record locking

Postby auphi » Sun Oct 21, 2012 7:44 pm

Hey all,

It is possible that this already exists somewhere, but after spending hours searching I was unable to find a satisfactory answer and wanted to share the solution that I came up with (since it took me a while to work out). There is no need to add a separate "last modified" column to your tables, as Xataface already stores that information in the dataface__record_mtimes table. You will need to add this code into the delegate class for each of the tables that you want to provide locking on.

In the table's delegate class (i.e. in the 'tablename'.php file), add
Code: Select all
   //Create a new hidden timestamp field with the page load time at the end of the form.
   function block__before_form_close_tag(){
      echo '<input name="timestamp" id="timestamp" type="hidden" value="'.time().'" data-xf-field="timestamp" />';
   }

   //Check if the data has been saved after we have already loaded the page, before overwriting, if so, return an error!
   function beforeSave(&$record){
      $recid = $record->getID(); //Get the record ID
      $rec = df_get_record('dataface__record_mtimes', array('recordid'=>$recid)); //Pull the last modified time from the dataface record
      $timestamp = $_POST['timestamp'];
      if($rec->display('mtime') > $timestamp) //Check to see if the last modified time is greater than the page load time
      {
         $msg = "ERROR: It appears that someone has recently modified this record, and your changes could not be saved. Here is the current record. Please re-enter your changes and try saving again.";
         header('Location: '.$record->getURL('-action=edit').'&--msg='.urlencode($msg)); //Reload the page so that the fields update.
         return PEAR::raiseError('',DATAFACE_E_NOTICE); //Return an error and don't save the record.
      }
   }


Voila! (You can test this by opening two copies of the same record in different tabs. Save one, and then try and save the other. You should receive the error message and the record will not be saved.)

Note that time() returns the current Unix timestamp in seconds. I used this because it is the format that Xataface stores its record information in, thus I didn't need to add a new "last modified" column to every table. That being the case, if two people both try and update the same record at the exact same time (ie. < 1 second apart) one record will still end up overwriting the other like it would have otherwise. If this is a concern for you, I would suggest adding a "last modified" column to all of your tables, and using microtime() for saving your "page load time" and "last modified" timestamps (and then of course you will have to modify this code a bit).
auphi
 
Posts: 20
Joined: Sun Oct 21, 2012 7:39 pm

Re: How to easily implement (faux) multi-user record locking

Postby shannah » Fri Oct 26, 2012 8:40 am

Great solution. I have been planning on adding some record versioning features to Xataface (which could be used to accomplish this) but have never gotten around to it.
--
Steve Hannah
@shannah78 (on twitter)
sjhannah.com blog
shannah
 
Posts: 4457
Joined: Wed Dec 31, 1969 5:00 pm


Return to Xataface Users

Who is online

Users browsing this forum: No registered users and 18 guests

Powered by Dataface
© 2005-2007 Steve Hannah All rights reserved