webhoes

Update field on save based on two other fields

Recommended Posts

Hello,

I have made a module, but I can't get it to work.

I have 2 fields with price (price and rrp). On save I want to calculate the difference in percentage and save it to the discount field.

It does not update the field. What am I doing wrong?

class UpdateDiscount extends WireData implements Module {

    public static function getModuleInfo() {
        return array(
            'title' => 'Custom discount updater',
            'version' => 1,
            'summary' => 'Auto update percentage based on prices.',
            'singular' => true,
            'autoload' => true,
            'icon' => 'money',
        );
    }

    public function init() {
        
// add a hook after the $pages->save, to issue a notice every time a page is saved
        $this->pages->addHookAfter('save', $this, 'updateProduct');
    }

    /**
     * Example1 hooks into the pages->save method and displays a notice every time a page is saved
     *
     * @param HookEvent $event
     *
     */
    public function updateProduct($event) {
        /** @var Page $page*/
        $page = $event->arguments[0];
        
        if($page->template != 'product') return;

        $price = $page->pad_price;
        $rrp = $page->pad_rrp;

        $discount = $rrp - $price;
        $percentage = $discount/$rrp * 100;

        $page->setAndSave('pad_discount', $percentage);
    }
}

Share this post


Link to post
Share on other sites

I think $event->arguments is a method not an Array/WireArray. 

EDIT: Also I think you might just want to set your hook before save not after and  or you might get into a recursive loop with setAndSave, and just reassign the $page as an argument. 

$page->pad_discount = $discount;

$event->arguments(0, $page);

 

  • Like 1

Share this post


Link to post
Share on other sites

Could not get something working with those changes.

After some more searches I came up with this, close to the examples but also still not working.

 

  public function init() {

// add a hook after the $pages->save, to issue a notice every time a page is saved
        $this->pages->addHookBefore('save', $this, 'updateProduct');
    }

    /**
     * Example1 hooks into the pages->save method and displays a notice every time a page is saved
     *
     * @param HookEvent $event
     *
     */
    public function updateProduct($event) {
        /** @var Page $page */

        $page = $event->object;

        //$page = $event->arguments('page');
        if($page->template != 'product') return;

        $fields = $page->fields;

        $price = $fields->get('pad_price');
        $rrp = $fields->get('pad_rrp');

        $discount = $rrp - $price;
        $percentage = $discount/$rrp * 100;
        $page->of(false);
        $page->set('pad_discount', $percentage);

        $this->message('test');
    }

Share this post


Link to post
Share on other sites

Damnnn...

Or you name your module properly instead of having .php as extension.

I could not find it among the modules, but I was confused with some other hooks that are not modules (like in ready.php) that just do their thing.

Luckily, it works now.

  • Like 1

Share this post


Link to post
Share on other sites

You can use a shorter form of the API to get the field values:

// instead of
$price = $fields->get('pad_price');
$rrp = $fields->get('pad_rrp');
// use
$price = $page->pad_price;
$rrp = $page->pad_rrp;

you also want to use the hookEvent saveReady instead of save, because 

Quote

These hooks provide more certainty and less need for error checking than hooking before or after Pages::save

See http://processwire.com/api/hooks/#before_or_after for details.

  • Like 1

Share this post


Link to post
Share on other sites

You should extend your if clause to ignore pages that are in trash (which can also be saved)

if ($page->template != "product" || $page->isTrash()) return;

 

Share this post


Link to post
Share on other sites
23 hours ago, webhoes said:

It does not update the field.

Are you sure your hook gets triggered? Always proceed step by step. I usually start with a hook that only outputs "triggered" via tracy:

bd("triggered!");

If you don't see the dump in the tracy bar, your hook does not fire and you have something else wrong (and that's the case here).

Try this one and then update the inner code:

$wire->addHookAfter('Pages::saveReady(template=product)', function($event) {
  $page = $event->arguments(0);
  // your logic here
  bd("hook fired!");
});

To update your field you don't need "setAndSave", just set your field's value like this:

$page->yourfield = 'yourvalue';

That's it 😉

  • Like 1

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.