Juergen

Tip how to track changes in field values (before and after)

Recommended Posts

Sometimes you need to track changes in certain values of a page to take an action afterwards.

In this example I will show you how to show a simple message after changes to inform the user that field values have been changed.

Put this piece of code inside your ready.php.

//Track changes
$pages->addHookAfter('saveReady', function($event)
{
  $page = $event->arguments[0];  
  if(!in_array($page->template->name, array('template1','template2'))) return; 
  $fields = array('field1','field2','field3','field4'); 
  $changedfieldsarray = array();
  foreach($fields as $field) {
   if ($page->isChanged($field)) {
     $changedfieldsarray[] = $page->fields->get($field, true)->label;
   } 
  }
  $fieldnames = implode(", ", $changedfieldsarray);
  $this->warning(sprintf(__("Following fields have been changed: %s"), $fieldnames ));
});

The first restriction in this example is to run this hook "aftersaveReady" and only on certain templates: in this case template1 and template 2. You need to rename this to your template names. Remove the following line of code if you want it to run on all pages (no restrictions):

if(!in_array($page->template->name, array('template1','template2'))) return;

Now you have to define the fields where you want to track changes (take a look at this line):

$fields = array('field1','field2','field3','field4');

In this case the fields are called "field1 to field4". Rename it to your field names.

The API call to track changes is "$page->isChanged('fieldname')". You will find more information at https://processwire.com/api/ref/page/is-changed/. Use a foreach to loop through the fields array and store all changed fields inside an array.

In the last step all the changed fields were outputted inside a message to inform the user. In this case I want to show the labels instead of the field names.

Only to mention: The changes will keep alive, so you have to delete it manually (http://cheatsheet.processwire.com/pagearray-wirearray/change-tracking/a-resettrackchanges/).

This little tutorial should only be a starting point for your own coding.

  • Thanks 3

Share this post


Link to post
Share on other sites

Here is another working method, that only shows changes once after save. It is based on this post from Ryan.

//Compare before and after values
$pages->addHookAfter('saveReady', function($event)
{
    $page = $event->arguments('page');
    if(!in_array($page->template->name, array('template1', 'template2'))) return; //restrict it to these templates only
    $fields = array('field1','field2'); //check only changes on these fields        
    $this->wire('pages')->uncache($page);//uncache new page
    $oldPage = $this->wire('pages')->get($page->id);// get old page  
    $changedfieldsarray = array();
    foreach($fields as $field) {
     if (($oldPage->$field) != ($page->$field)) { //this is the comparison between before and after
      $changedfieldsarray[] = $page->fields->get($field, true)->label;
     }
    }
    if(count($changedfieldsarray) > 0) {
     $fieldnames = implode(", ", $changedfieldsarray);  
     $this->warning(sprintf(__("Following fields have been changed: %s"), $fieldnames )); 
    }      
});

It uses the uncache method to compare stored values from the DB and the new ones entered in the form. This informs the editor only once directly after form submission. If the editor push the save button once more and nothing was changed, the message will not be shown again. This is the main difference between this and the previous method.

Attention: This method uncaches the page and therefore all entered values will be cleared after pressing the submit button and no sucessfull saving of the page - so use this method with care.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Here is a new created version to track changes which works without any problems and you dont have to take care about the deletion of input values if the page was not saved successfully (like in the version before)

Put this little piece of code inside your ready.php.

//Compare before and after values and output a warning message
$pages->addHookAfter('Pages::saveReady', function($event) {
    $page = $event->arguments('page');
    $page->of(false);
    //configuration: change it to your needs
    $templates = ['event_businessvacations', 'event_dates', 'event_events', 'event_specialbusinesshours']; //array of templates where this hook should run
    $fields = ['summary', 'body']; //array of fields which should be checked
    //configuration end
    if(in_array($page->template->name, $templates)){
    $changedfields = [];
    foreach($fields as $fieldname){
    if ($page->isChanged($fieldname)) {
        // Page as it is in the DB
        $oldPage = wire('pages')->getById($page->id, array(
        'cache' => false, // don't let it write to cache
        'getFromCache' => false, // don't let it read from cache
        'getOne' => true, // return a Page instead of a PageArray
         ));
         $changedfields[] = $oldPage->fields->$fieldname->label;          
    }    
    }
    $changedfields = implode(", ", $changedfields);
    if(!empty($changedfields)){
     $this->warning(__("The following fields have been changed: {$changedfields}"));
    }
  }
});

Change the configuration block to your needs (template names, field names).

This little code snippet outputs only a warning message which fields have been changed - not more or less, but you can also run some other logics - its up to you.

Note: Works also with repeaterfields, but you can only check the repeaterfields for changes in general. It is not possible to check for specific fields inside the repeater.

  • Like 6

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.