Page 1 of 1

Record Tracking

PostPosted: Mon Oct 22, 2007 7:47 pm
by ADobkin
What is the correct procedure to track the creator and creation time of a record, as well as the last updated time? Specifically, what field names and data types should be defined in the database, and what other settings (i.e. fields.ini, etc.) are necessary to make this information display properly in the record view?

Thanks,
Alan

PostPosted: Tue Oct 23, 2007 12:52 am
by shannah
1. Tracking creator.
Code: Select all
function beforeInsert(&$record){
    $auth =& Dataface_AuthenticationTool::getInstance();
    $username =& $auth->getLoggedInUsername();
    $record->setValue('creator', $username);
}


This assumes that you have a field called 'creator' in your table.

2. Tracking creation time.

There are many ways to do this but I generally do this.
a. Create a datetime field and allow null values, let's say its name is 'date_created'.
b. In the fields.ini file:
Code: Select all
[date_created]
    widget:type=hidden
    timestamp=insert


3. Tracking modification time

a. Create a datetime field and allow null values, let's say its name is 'date_modified'
b. In the fields.ini file:
Code: Select all
[date_modified]
    widget:type=hidden
    timestamp=update


-Steve

PostPosted: Tue Oct 23, 2007 6:37 am
by ADobkin
Thanks for the info! I have a couple of follow-up questions:

1) Is it preferred to let Dataface handle the timestamps, or to use type TIMESTAMP fields in MySQL and have them updated automatically by the database (on the back-end)?

2) If I have other datetime or timestamp fields in the table, how do I ensure that Dataface uses the right one when showing the "Last updated" statement at the top of the current record view? I noticed the functions getCreated and getLastModified (referencing $createdField and $lastModifiedField respectively) in Record.php. Should my field names be specified to override these values, and if so, where should this be defined?

Thanks,
Alan

PostPosted: Tue Oct 23, 2007 7:43 am
by Guest
Is it preferred to let Dataface handle the timestamps, or to use type TIMESTAMP fields in MySQL and have them updated automatically by the database (on the back-end)?


All things being equal I would say 'yes' it is better to do it in the database. However I have personally had a lot of trouble getting mysql to track both the creation time and the modified time. You can only have one timestamp field per table, and this field can either track the modified time or the creation time, not both.
Of course, if you are using MySQL 5 you could write a trigger.

If I have other datetime or timestamp fields in the table, how do I ensure that Dataface uses the right one when showing the "Last updated" statement at the top of the current record view? I noticed the functions getCreated and getLastModified (referencing $createdField and $lastModifiedField respectively) in Record.php. Should my field names be specified to override these values, and if so, where should this be defined?

Dataface tries to guess which field is your update time based on the field name. Currently you cannot override this field name, but you can override the modified time value using the getLastModified() delegate class method.

e.g.
Code: Select all
function getLastModified(&$record){
     return strtotime( $record->strval('last_updated') );
}


Note that this method should return a unix timestamp.

-Steve

User tracking

PostPosted: Tue Oct 23, 2007 11:19 am
by ADobkin
I decided to try abstracting the user name by using user IDs instead from the users table. I am also keeping track of both the user who added the record and the one who last modified it, like this:

Code: Select all
        function beforeInsert(&$record){
                $auth =& Dataface_AuthenticationTool::getInstance();
                $user =& $auth->getLoggedInUser();
                $record->setValue('_uidAdd', $user);
        }

        function beforeUpdate(&$record){
                $auth =& Dataface_AuthenticationTool::getInstance();
                $user =& $auth->getLoggedInUser();
                $record->setValue('_uidMod', $user);
        }


Then, I have a definition in valuelists.ini to display the actual user name:

Code: Select all
[Users]
__sql__ = "SELECT _user_ID, userName FROM users ORDER BY userName"


Do you see any problems with this approach? For example, will I be losing out on certain features by not using a "creatorField" that Dataface can "guess" (since "uidMod" doesn't match the hard-coded patterns)?

Thanks,
Alan

PostPosted: Tue Oct 23, 2007 11:43 am
by shannah
This looks like a pretty good approach to me. Can't think of any down-sides off the top of my head.

-Steve

Possible bug with Dataface timestamp update

PostPosted: Wed Oct 24, 2007 2:53 am
by ADobkin
I am noticing some weird behavior with this:

[quote="shannah"]3. Tracking modification time

a. Create a datetime field and allow null values, let's say its name is 'date_modified'
b. In the fields.ini file:
Code: Select all
[date_modified]
    widget:type=hidden
    timestamp=update


I've done a bit of testing, and it seems to work fine for records that are created with Dataface. Dataface apparently sets both the date created and date modified to the same values when the record is created, which is perfectly fine.

However, with a record created outside of Dataface (such as an import or manually inserted via phpMyAdmin), the date_modified field is initially set to either NULL or a "zero" date: 0000-00-00 00:00:00, which is also fine. The problem is that Dataface refuses to update this field on further edits to the record. If I change the datetime value to something non-zero, for example 0000-00-00 00:00:01, then Dataface accepts it and updates it properly.

Is this a bug in Dataface? My workaround is to now set the field to NOT NULL and use a default value such as DEFAULT '2000-01-01 00:00:00'. This appears to work well both in and out of Dataface, and for both the created and modified fields.

Thanks,
Alan

PostPosted: Wed Oct 24, 2007 8:01 am
by shannah
Likely a bug in dataface... will look into it.

PostPosted: Wed Oct 24, 2007 8:10 am
by ADobkin
Thanks. In case you are not able to confirm the bug, I realized after I posted this message that I had converted my fields from timestamp to datetime in MySQL rather than creating them from scratch. I don't think that should make a difference, especially for new records, but I thought I'd mention it just in case....

getLoggedInUser() for userID (

PostPosted: Mon Nov 05, 2007 2:39 pm
by ADobkin
I am having a problem with my user logging example above:

Code: Select all
function beforeUpdate(&$record){
        $auth =& Dataface_AuthenticationTool::getInstance();
        $user =& $auth->getLoggedInUser();
        $record->setValue('_uidMod', $user);
}


The value is set to 1 no matter which user is logged in. Is there a different function I should be using other than getLoggedInUser()? Or, do I need to create my own function for this? I poked around a bit in the AuthenticationTool source file, and it looks like it doesn't keep track of the actual numeric user ID (primary key). Please confirm.

Thanks,
Alan

PostPosted: Mon Nov 05, 2007 2:58 pm
by shannah
Your problem is that $user is a Dataface_Record object and not a string.

You have 2 options here:
1. Use the getLoggedInUsername() method instead of getLoggedInUser()
e.g.
Code: Select all
$user = $auth->getLoggedInUsername();
$record->setValue('_uidMod', $user);


or

2. Use the value of the username field in the setValue() call:
e.g.
Code: Select all
$user = $auth->getLoggedInUser();
$record->setValue('_uidMod', $user->val('username'));

Note that the above assumes that the column you use to store usernames is called 'username'.

-Steve