netcarver

Prioritising hooks for same event.

8 posts in this topic

Am I right in thinking that multiple hooks that are added for the same event can be prioritised by doing something like this...

$session->addHookAfter( 'login', $this, 'myLoginHook', array('priority'=>xyz) );

Where xyz is the relative priority for the hook and the lower the value, the earlier it will be called as the hooks are executed?

1 person likes this

Share this post


Link to post
Share on other sites

That's correct. At least, that was the intention. It's one of those things I thought would come in more handy than it has… I'm not aware of it ever being used. So I think the only time it has even been tested is when I originally coded it in there (at which time it was working). No recent confirmation of current functionality though. A quick glance in the code seems to indicate that it should work as intended, though please let me know if you find otherwise.

Default priority level is 100 (that's what gets assigned when none assigned).

1 person likes this

Share this post


Link to post
Share on other sites

Ok, an update. To get two of my modules to work well together I do need this functionality. I basically want the 2-factor login module to get first crack at the hook before the login alarm gets to log/email the users.

I set the priority in the 2-factor module to 10 and in the alarm module to 2000 (just to be sure) however on adding a die(__CLASS__) to both hook handler routines I could see that the alarm module was getting called first. An unexpected result, but I've now found out why.

It turns out that I was hooking the login event in slightly different ways and this does seem to effect the order the routines get called in. In the 2-factor module I was doing this...

$this->addHookAfter( "Session::login", $this, 'my2FactorHook', array('priority'=>10));

Whilst in the alarm module I was adding the hook differently...

$this->session->addHookAfter( "login", $this, 'myAlarmHook', array('priority'=>2000));

Switching the 2-factor init() routine over to using $this->session->addHookAfter('login'...) has everything called in the right order.

1 person likes this

Share this post


Link to post
Share on other sites

Glad you got it working. Static hooks ("Session::login") are treated separately from direct hooks. The direct hooks are more specific so they get executed before the static ones. But I wasn't really thinking much about priority level when building this, so not sure if that's the way it should be or not.

Share this post


Link to post
Share on other sites

Ok, that certainly explains the result. But it makes me wonder if a unified approach to hooks might be more logical than having a set of static hooks and local hooks unless there was a specific reason for going for two sets?

Share this post


Link to post
Share on other sites

Static hooks apply to all instances of a class, whereas direct instance hooks apply to just 1 instance (the one you assign it to). For example, you'd use a static hook if you wanted to hook into or add some new method to all Page instances. Whereas, if you are hooking any API variable ($session, $pages, $modules, etc.), it's better to use a direct/instance hook since there is only ever going to be 1 instance of those variables anyway. While you could use a static hook anywhere, direct hooks are a little more efficient because they are stored with the actual object instance rather than in the larger pool of static hooks. Meaning, direct/instance hooks result in less for ProcessWire to sift through when executing hooks (though it probably doesn't matter much in the larger scheme of things). But this is also the reason why they aren't prioritized together, as they are stored in different places.

1 person likes this

Share this post


Link to post
Share on other sites

Ah, right. I'll just have to make sure I install the hooks consistently next time then.

1 person likes this

Share this post


Link to post
Share on other sites

Just thought you guys might like to know that the priority setting just got another user :)

Needed to solve the conflict between RedirectIds and 404Search modules.

Thanks again Ryan for thinking of everything!

6 people like this

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.

  • Similar Content

    • By bmacnaughton
      I have a hook that creates a page for a subset of the pages on our site. It uses the saved page's name as part of the created page's name.
      The problem I am having is that my hook, attached to Pages::saved(), is being called even when the page save failed because of missing fields. Is there a way I can tell that the page save failed due to missing fields?
       
      Never mind - it does succeed; it just issues warnings about required fields.
       
    • By gebeer
      Hello,
      I noticed that the Pages::added hook gets called twice. PW 3.0.62.
      To test , add this to admin.php
      wire()->addHookAfter('Pages::added', function($event) { bardump('added'); // needs Tracy Debugger }); Can anyone confirm this?
      It gives me trouble when adding a hook that skips the page add step (for users), following Pete's concept. There will always be created 2 new pages which I need to avoid.
      Is it a feature or a bug?
       
    • By bmacnaughton
      I have a Page Table field that, for new entries, I want to construct the name for.
      When I click the Add New button the page being added has already been given a random name like: 20170422-003744.
      I wish to
      1) change that name so it's obvious it is a temporary name
      and 
      2) when either Publish or Save + Keep Unpublished is clicked, set the name of the page based on the content entered.
      What hooks can I use to accomplish 1 and 2?
       
      thanks.
       
    • By ---
      So I discovered in this topic (
      ) that I can cancel all hooks after my own hook. Now I want something like that.
       
      I want my hook which is called on page render to cancel all other events, also the after page render and the before page render methods, is this possible?
      This only need to be done when some conditions are met.
       
      /** method replaces original page::render method and is called with hook priority one */ method onPageRender (HookEvent $event) { if (my condition is true) { $this->cancelHooks = true; // to cancel all hooks to page::render // how to cancel after Page::render events // how to cancel before Page::render events } } Is this possible at all?
    • By ---
      I have created a hook with priority one because I want it to run asap. Now I want this same hook to prevent all other hooks from running, is this possible, if so, how can I achieve that?
      For example, normally hooks would run like this:
      hook 1 -> hook 2 -> hook 3 -> hook 4 -> etc.
      Now I want it like this:
      hook 1 -> hook 2 -> hook 3 -> hook 4 -> etc.