Jump to content

How to get old page values in a ProcessWire page save hook, and some other notes on save hooks


thetuningspoon
 Share

Recommended Posts

I wrote this a while back for my company's internal documentation and just realized it might be a benefit to others on the forum, so here it is!

Checking whether a field was changed

To check whether a specific field was changed you can do $page->isChanged(‘field’). This can only be done before Pages::save, since the save clears change tracking by default.

Getting the values of a page before they were changed, from within a hook before Pages::save

Method 1: The hacky way

$clone = clone($page);
$e->wire('pages')->uncache($clone);
$oldP = $e->wire('pages')->get($clone->id);

$oldP then represents the page and all its values as they were before any changes were made. Again, this will only work for hooks that run prior to Pages::save.

Method 2: Using change tracking to get the old values

If change tracking is set to track values, then the above is not necessary. In this case, calling $page->getChanges(true) will return an associative array of fields that changed and each field's prior value. Note that the value itself is also an array, since it is designed to be able to track multiple changes over the course of a single request/response cycle.

Tracking of values is turned off by default (for efficiency sake), and there is no global switch to turn it on and off. To enable tracking of values, you must call $page->setTrackChanges(Wire::trackChangesOn | Wire::trackChangesValues) before any changes are made to the page that you want to track.

Here is an example of how you can enable value tracking in ProcessWire's page editor:

$this->addHookBefore("ProcessPageEdit::execute", null, function($e) {
	$p = $e->pages->get((int)$e->input->get('id'));
	if($p->template == 'event-registration') {
		$p->setTrackChanges(Wire::trackChangesOn | Wire::trackChangesValues);
	}
});


Running hooks on both page saves and field saves

Please note that using the following hooks is preferable if you want the hook to run both when individual fields are saved as well as the whole page:

Pages::savePageOrFieldReady https://processwire.com/api/ref/pages/save-page-or-field-ready/ (for before a save)

Pages::savedPageOrField https://processwire.com/api/ref/pages/saved-page-or-field/ (for after a save)

Getting changes in a hook after Pages::save

Note the $changes parameter passed to Pages::saved and Pages::savedPageOrField allows you to check which fields were changed during the save, even though the save is already completed. Using this is sometimes preferable to using a Pages::saveReady or Pages::savePageOrFieldReady hook since you don’t have to worry about the page cache or something else in your code preventing the original save from completing. A $values array is also provided, which is populated only if change tracking is set to track values (see above)

Page cache issues when hooking before Pages::save

Page cache issues may occur when you try to save another page inside of a before save hook (Pages::saveReady or Pages::save). A page save normally clears the entire page cache, which means any page fields on the page you were originally trying to save will have their values reset. So if you have to save another page inside of a before save hook, just use $page->save([‘uncacheAll’ => false]) to prevent the cache from being cleared.

Preventing hooks from running on a particular save

To prevent any hooks from running on a particular page save, you can use $pages->save($page, [‘noHooks’ => true])

  • Like 6
  • Thanks 1
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...