Jump to content

Module which should (re)save a page field triggers an endless loop


theoretic
 Share

Recommended Posts

Hello everybody! And thanks for Processwire!

It appears that i have an interesting case concerning page fields resaving via modules. Let's suppose we're making a module which should run every time when a page is saved. Our module should calculate a value based on the values of some page fields, place this value to a dedicated field (in my case it's called 'mark') and save the page again. Below is the example of possible module code:

public function init() {
		$this->pages->addHookAfter('save', $this, 'hookCalculateMarks'); 
	}

private function calculateMarks($page) {
		$page->of(false);
		//doing some calculations...
		//$page->save(); //will trigger endless loop calling hookCalculateMarks again and again!
		$page->of(true);

		$this->message("Marks calculated.");
		$this->calculated = true;
		}

	public function hookCalculateMarks($event) {
		$page = $event->arguments[0];
		$this->calculateMarks($page);
	}

The problem is that the commented page->save() triggers a save event which triggers the hookCalculateMarks which triggers page->save() which triggers the hookCalculateMarks which... oops, my mysql server has gone away.

Tried to use a variable like $calculated...

	var $calculated = false;

	//some code skipped

	private function calculateMarks($page) {

		$page->of(false);
		//$page->save(); //will trigger endless loop calling hookCalculateMarks again and again!
		$page->of(true);

		$this->message("Marks calculated.");
		$this->calculated = true;
		}


	public function hookCalculateMarks($event) {
		$page = $event->arguments[0];
		if( $this->calculated ) return;
		$this->calculateMarks($page);
	}

 

...but the problem is still present. Endless loop again.

So what are the best practices for this case? What is the safe way to (re)save a field value afgter a page is saved?

Thanks in advance!

 

Link to comment
Share on other sites

Hello theoretic,

maybe you can try with add hook after "saveReady", and in that case also leave save part to PW api.
 

// pseudo example for your case
public function init() {
	$this->pages->addHookAfter('saveReady', $this, 'hookCalculateMarks'); 
}

public function hookCalculateMarks($event) {
	$page = $event->arguments[0];
	// if not desired template return
	if($page->template != 'your_template_name') return; 
	// eg. check if field marks is empty or 0
	if($page->marks < 1){		
		// some calculations... eg. using other page fields	
		$page->marks = $page->field_x + $page->field_y;		
	}	
}

As you can see there is no page "save" part.
This hook will check and set field value, and after it ProcessWire API will do the rest of the job.

Regards.

Link to comment
Share on other sites

Thanks to all! Using  SaveReady is more logical in my case because i need the recalculation of my field (marks) just before the page will be saved. Works like a charm!

As to setAndSave, it will be more logical to use it in cases when there's no need to save the whole $page. However it's a very interesting approach also, thanks!

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...