Jump to content

Page[s]::trash(template=foo) vs Page[s](template=foo)::trash


Recommended Posts

I am preventing pages with a specific template from being deleted. I have it working with Pages::trash(template=foo), Pages::delete(template=foo).

I'm after a better understanding of why this works please.

  1. Why does it work with Pages and not Page, what's the difference?
  2. Why is it Pages::trash(template=foo) and not Pages(template=foo)::trash?

I have read the docs page on hooks but still don't quite get it. ๐Ÿฅด

Link to comment
Share on other sites

That are good and important questions if you want to understand hooks ๐Ÿ™‚ย 

Pages::trash() is a hook that you attach to the method "trash" of the "Pages" class (that's the file /wire/core/Pages.php). In that file you'll find the method ___trash() which indicates that it is hookable. You'll also find helpful comments on top of that method in the code.

The same concept applies to Page::trash() where the hook is attached to the method trash() of the "Page" class (which is the file /wire/core/Page.php) and represents a single page object.

50 minutes ago, DrQuincy said:

Why is it Pages::trash(template=foo) and not Pages(template=foo)::trash?

See my link in the signature "afraid of hooks" - does that answer your question?

  • Like 1
Link to comment
Share on other sites

Thank you.

I never knew about the relationship between the hook and the class and function name so that is a huge help. Studying the Page and Pages class shows me how different they are โ€” so that makes sense! ๐Ÿ™‚

I'm still not 100% on the second point. From reading about hooks I thought the first condition in parenthesis in a hook was a selector and the second was a filter for fields. So to me, this should work since I want to filter out saves where the page has a specific template:

\ProcessWire\wire()->addHookBefore('Pages(template=typeface)::saveReady', function(\ProcessWire\HookEvent $event) {

	\ProcessWire\wire('session')->error('Hook called');

But instead this is what works:

\ProcessWire\wire()->addHookBefore('Pages::saveReady(template=typeface)', function(\ProcessWire\HookEvent $event) {

	\ProcessWire\wire('session')->error('Hook called');

Why is that? I'm sure I'm missing something really obvious!

Link to comment
Share on other sites

The part in the braces tells PW to apply a selector. The position where you add this selector tells PW where to apply the selector. And that "WHERE" depends on the hook and it's structure.

In your example you hook Pages::saveReady, which looks like this:


That means the object is the "Pages" class and the method is the "saveReady" function. As you can see above on line 2287 that method takes one argument: The "Page" object that is being saved.

That means:

  • In the HookEvent $event, the object will be the "Pages" class. Try that with tracy: bd($event->object)
  • In the HookEvent, you'll have one argument and that will be the "Page" object being saved. Try bd($event->arguments(0))
  • You could also use $event->arguments('page') because the first argument of saveReady() is $page. If it were $foo you could do $event->arguments('foo')
  • If you apply a condition like Pages::saveReady(template=foo) that means that you apply the selector "template=foo" to the first argument of the saveReady method which is the "Page" object (on line 2287) that is referenced as $page.

What you are doing when using Pages(template=foo)::saveReady is that you apply the selector "template=foo" to the "Pages" class, but the Pages class is not a single Page object and therefore has no template!

Hope that makes sense ๐Ÿ˜„ย 


  • 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.
  • Create New...