Jump to content

Prioritising hooks for same event.


Recommended Posts

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?

  • Like 2
Link to comment
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).

  • Like 3
Link to comment
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.

  • Like 3
Link to comment
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.

Link to comment
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.

  • Like 1
Link to comment
Share on other sites

  • 1 year later...

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!

  • Like 8
Link to comment
Share on other sites

  • 3 years later...

I thought it might be worth mentioning - given remarks above - that another three years on this feature is still getting new users :D

This time, it's to fire off my own page-renaming module before the Custom Upload Names module makes updates when the page name changes.

This has allowed the modules to work together really easily and, I suspect, saved quite a lot of hard work!

  • Like 4
Link to comment
Share on other sites

  • 6 months later...

Is it possible to control Processwire hook priorities, other than what the module devs agree on?

For example, I have installed

  • Redirects
  • 404Logger
  • 404Search

The behaviour  I want is:

  1. Redirect if possible, else
  2. Log page not found, and
  3. Do 404 search

The behaviour I have is

  1. Log page not found, and
  2. Redirect if possible, else
  3. Do 404 search

If I could lower the priority of 404Logger, then I guess this would work as I need it to.  I imagine I can modify the module, but I'd want this to be update survivable.




  • Like 2
Link to comment
Share on other sites

  • 2 years later...

As of now I am a user of this feature too) Thanks to @adrian's link.

I did need it to fix this issue. If you read through the linked thread you'll see that I confused module autoload order with hook order. Actually I thought that the module, that gets loaded first, would add the hook first (or last). So the autoload order would affect hook order. I did play with autoload order of the modules without success. Why is it not it the case?

If it was, there could a chance to add an option to override module autoload order in admin, making it adjustable without code hacks , solving this question.

  • Like 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

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By rjgamer
      is there a hook after the current (active) page got created? Or which method got called in the Page class after the Constructor of the current page got initialized?
    • By Kiwi Chris
      I need to restrict editing access based on both the user role, and the value of a sub-field in a page reference field.
      eg $page->competition->closingDate 
      There's some discussion about restricting editing access based on role, and that works, but when I try to access the page via the method @Robin S suggests, the page returned is an admin page rather than the page being edited, so I don't have access to the edited page's fields.
    • By picarica
      so i am trying to put CustomHooksForVariations.module, a custom module, i am placing it into site/modules direcotry yet my modules page in admin panel gives me errors
      so this is the screen show when i refresh modules, i dont know why the shole hook is written on top of the page :||

      and this next image is when i try to install it, i saw that it is not defiuned modules.php but it shouldnt need to be ?, any ways i dont want to edit site's core just to make one moulde work there has to be a way

    • By Andi
      Continuing my journey into PW hooks, I'm trying to find a way to retrieve all images from a page that explicitly *do not* have a certain tag (or tags) attached to them.
      Found this post from 2015
      But I'm wondering if there's a more elegant way to go about this.
      Let's say I have a multi-image field called "images_header" and instead of
      $page->images_header->findTag('mytag'); I would like to do this:
      $page->images_header->excludeTag('mytag'); So I'd be able to do
      // find images that don't have the tag "mytag" $images = $page->images_header->excludeTag('mytag'); // check if there's any images if (count($images)>0) { // do something.. } Would this be possible by hooking into Pagefiles somehow?
      There's this bit in /wire/core/Pagefiles.php Line 626 that I'd basically just need to reverse (or at least in my mind 😄 )
      public function findTag($tag) { $items = $this->makeNew(); foreach($this as $pagefile) { if($pagefile->hasTag($tag)) $items->add($pagefile); } return $items; } Any ideas on how this could be done in a graceful manner?
      Thanks in advance!
    • By Andi
      Getting a little deeper into the ProcessWire state-of-mind here. I seriously think I wouldn't have come back to webdev if it wasn't for this wonderful little gem of a CMS.
      I have an "Options" field added to all users on a site. If the user has anything other then "default" selected, I would like to show a permanent message in the admin like the one in the screenshot, only so that the user can't close it. As a friendly reminder that he changed that option from default to something crazy 🙂
      I've read up on how to send messages to users, but where would I hook into to make this show up all the time in the backend?
      Thanks in advance!

  • Create New...