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...