Jump to content

Changing a field then saving via hook


msavard
 Share

Recommended Posts

I've spent way too much time trying to figure this out so now I just have to ask.

I added an option to the save button when editing a page. What I want it to do is, when clicked, send an email out to the appropriate person, change a field on the page, then save. I have everything working up until the change a value on the page and save. I can't seem to figure out how to do this. I really don't understand what I'm doing. So far the email part works because I just smashed together various bits and pieces from the forums.

Here is the hook that adds the button

$wire->addHookAfter('ProcessPageEdit::getSubmitActions', function($event) {
  $actions = $event->return; // array of actions indexed by name
  $page = $event->object->getPage(); // page being edited

  // add a new action to process the Change of Address request if
  // this page uses the change of address template
  if ($page->template == 'Change_Of_Address' && $page->yes_no == false){
  $actions['Process Form'] = [ 
    'value' => 'process', 
    'icon' => 'address-card', 
    'label' => '%s + Process', 
    'class' => '', 
  ]; 
  $event->return = $actions;
}
}); 

And here is the modified code that attempts to change a field value and save the page. I removed all the part that creates/sends the email.

$wire->addHookAfter('ProcessPageEdit::processSubmitAction', function($event) {
  $action = $event->arguments(0); // action name, i.e. 'hello'
  $page = $event->object->getPage(); // Page that was edited/saved

  if($action === 'process') { 
      $page->yes_no = true;
      $pages->saveField($page, 'yes_no');
      $notice = new NoticeWarning("This address change has been sent to the appropriate crew.");
      $notice->icon = 'address-card';
      $event->notices->add($notice);
      $event->object->setRedirectUrl('../');
    }
});

I get an error on the $pages->saveField line saying:

Call to a member function saveField() on null

Can anyone offer some help on this? If there is an easier way to do this other than using hooks and adding buttons I would welcome that as well.

Link to comment
Share on other sites

Oops...I just came across an answer in this post. I spent all day yesterday trying to figure this out and then I find the answer a couple minutes after finally asking the question. 🤦‍♂️

If I use the $page->setAndSave() method then it works. 

I would still be interested to hear if there is a better way to accomplish this task.

Link to comment
Share on other sites

21 hours ago, msavard said:
$pages->saveField($page, 'yes_no');
21 hours ago, msavard said:
Call to a member function saveField() on null

This error means that you call ->saveField on "null". That means that $pages is "null" in your case. Why is it null? Because it's not defined in your hook. Inside the hook you don't have access to all the PW API variables (like $pages, $sanitizer, etc). There you either need to first make them available (like $pages = $this->wire->pages) or just use the object-syntax: $this->wire->pages->saveField(...)

Of course as you mentioned $page->setAndSave(...) does also work (because $page is defined in your hook, so you can work with it).

21 hours ago, msavard said:

Can anyone offer some help on this? If there is an easier way to do this other than using hooks and adding buttons I would welcome that as well.

It depends a lot on your use case. You could also add a checkbox to your page and then hook into Pages::saveReady or Pages::saved - there is a small but important difference here: "saveReady" is triggered BEFORE the page is saved, "saved" is triggered AFTER. That means in a saveReady hook you can just set page properties (aka field values) without saving the page (because the page is saved afterwards). In a "saved" hook it's not enough to just change page properties, because the save has already happened so you just change the field values but don't save your changes.

// ##### in a saveReady hook

$page->foo = "My foo value";
// page save happens here

 

// ##### in a saved hook

// page save happened here
$page->setAndSave('foo', 'My foo value');

In your case the example with a checkbox could look like this:

<?php namespace ProcessWire;
// site/ready.php

$wire->addHookAfter("Pages::saveReady", function($event) {
  $page = $event->arguments(0);
  
  // only execute on yourtemplate pages
  if($page->template != 'yourtemplate') return;
  
  // checkbox not checked --> dont execute
  if(!$page->yourcheckbox) return;
  
  // checkbox is checked, send email
  $mail = new WireMail();
  // ...
  $mail->send();
  
  // reset the checkbox
  $page->yourcheckbox = false; // 0 would also work
  
  // page will be saved after this hook
  // here you could also change other field's values
  $page->otherfield = 'new value';
});
    

 

  • Like 1
Link to comment
Share on other sites

Thank you. That is very helpful. I can see there is a lot of power in using hooks. I'll have to look into those more. 

I think I will eventually do this as a batch (find all the ones that aren't checked, process them, send an email, etc) but I want to make sure everything is working before I set it loose on it's own (and what type of errors might crop up). I trust processwire, but I don't trust me driving processwire! ☺️

Thanks again.

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

×
×
  • Create New...