Jump to content

My first hook to customise the page title for a specific template


LAPS
 Share

Recommended Posts

I am using PW version 3 and I would like to define a hook for a my specific template applicable to both the site (front-end) and the ProcessWire admin.

My template is named 'user' and has 'last_name' and 'first_name' input fields. The hook should set the 'title' to 'last_name' + 'first_name' on creating and updating data.

I tried the following, without success:

In the admin panel, 'Edit Template: user' > 'Files' tab, I set 'Prepend File' to 'hooks/user_int.php'. In the 'hooks/user_int.php' file I wrote:

wire()->addHookBefore('Pages::saveReady', function($event) {
    $page = $event->arguments('page');
    $page->title = $page->last_name . " " . $page->first_name;
});

However, when I create/edit and save a 'user' page it does not seem to work: 'title' is not set to 'last_name' + 'first_name'.

What am I doing wrong? What should I do?

Link to comment
Share on other sites

hi laps,

i strongly recommend using tracy during development, then you can see instantly whats going on in most of the cases...

$wire->addHookAfter('Pages::saveReady', function($event) {
  $page = $event->arguments('page');
  bd('page title: ' . $page->title);
});

just put this in your /site/ready.php and save any page you like and you'll see the output in your debug bar:

5a3ba8dba8ded_2017-12-2113_27_32-.png.b5d5ddb7b5465308e16bbc53cbf63bf0.png

26 minutes ago, LAPS said:

In the admin panel, 'Edit Template: user' > 'Files' tab, I set 'Prepend File' to 'hooks/user_int.php'. In the 'hooks/user_int.php' file I wrote:

just put it in your /site/ready.php file - you don't need to define anything else. Prepend and append files are for rendering the frontend.

  • Like 3
Link to comment
Share on other sites

1 hour ago, bernhard said:

just put it in your /site/ready.php file - you don't need to define anything else.

By putting the code in the '/site/ready.php' file it does work. Since I need to use the hook only for my specific 'user' template pages, I could use an 'if' statement something like this:

wire()->addHookBefore('Pages::saveReady', function($event) {
    $page = $event->arguments('page');

    if ($page->template->name == 'user') { 
        $page->title = $page->last_name . $page->first_name;
    }
});

However, is there a way or a best practice to state the hook code somewhere so that I can explicitly indicate that the hook just run (and load) for the 'user' template, avoiding to use 'if' statements?

Maybe, I want my hook to apply to all instances of a class but I am not sure how to proceed with coding and statement/file positioning.

 

1 hour ago, bernhard said:

[...] i strongly recommend using tracy during development, [...]

Thank you, I will give a look at Tracy debugger.

 

  • Like 1
Link to comment
Share on other sites

28 minutes ago, LAPS said:

However, is there a way or a best practice to state the hook code somewhere so that I can explicitly indicate that the hook just run (and load) for the 'user' template, avoiding to use 'if' statements?

the if-statement is totally fine. you can also use conditional hooks: https://processwire.com/blog/posts/new-ajax-driven-inputs-conditional-hooks-template-family-settings-and-more/#new-conditional-hooks

don't think that there is a best practice or any performance difference between conditional hooks and if statements but that's just a wild guess...

  • Like 1
Link to comment
Share on other sites

27 minutes ago, bernhard said:

Among the many tests, I tried to use the conditional hook 'Page(template=user)::saveReady' without success:

wire()->addHookBefore('Page(template=user)::saveReady', function($event) {
    $page = $event->arguments('page');
    $page->title = $page->last_name . " " . $page->first_name;
});

The linked documentation refers to the 'Page::changed' hook. Are conditional hooks only available for 'Page::changed' hooks?

Link to comment
Share on other sites

6 minutes ago, LAPS said:

The linked documentation refers to the 'Page::changed' hook. Are conditional hooks only available for 'Page::changed' hooks?

no, but saveReady belongs to the pages class, so the template condition won't work. You could use Page(template=user)::changed(0:first_name, 1:last_name) i guess...

but saveReady hooks with an if statement are totally fine ;)

Link to comment
Share on other sites

4 minutes ago, bernhard said:

You could use Page(template=user)::changed(0:first_name, 1:last_name) i guess...

I also tried to use your hint without success:

wire()->addHookBefore('Page(template=user)::changed(0:last_name, 1:first_name)', function($event) {
    $page = $event->arguments('page');
    $page->title = $page->last_name . " " . $page->first_name;
});

 

Link to comment
Share on other sites

use tracy and debug $event:

wire()->addHookBefore('Page(template=user)::changed(0:last_name, 1:first_name)', function($event) {
    bd($event);
});

hookevents ($event) always have the object (class) and the arguments (parameters), in this case $event->object is the class ($page you are looking for) and 

ps: i prefer addHookAfter most of the time to be sure that the method itself does not overwrite the value again... don't know if that makes sense in your case but just wanted to point out that you have to take an eye on that.

5a3bd0b590145_2017-12-2116_17_34-EditPage_admindatatables_to.png.8ad1d58e1b2c67ecc64ddecb7ba69e5d.png

you see very well that $event->object = user, $event->arguments(0) = field name, (1) = old value, (2) = new value.

it did only work for me like this:

wire()->addHookBefore('Page(template=user)::changed(0:email)', function($event) {
  bd('user changed');
  bd($event->arguments(0));
  bd($event->arguments(1));
  bd($event->arguments(2));
  bd($event);
});

id didn't work with multiple fields in the changed() part. don't know why. you can investigate this on your own with the help of tracy and some try&error. 

  • Like 1
Link to comment
Share on other sites

You could also use the "Cache" field (not installed by default) and create a "fullname" cache field to add to user template. In the field setting add the fields "first_name last_name" to save on that field. 

Or add a property "fullname" hook to the User page

wire()-addHookProperty("User::fullname", function($event){
	$event->retuen = $event->object->first_name . " " . $event->object->last_name;
});

 

  • Like 2
Link to comment
Share on other sites

@Soma I think either "cache" nor "addHookProperty" is not the solution in my case. I would like to store the full name in the title. Both "cache" and "addHookProperty" seem do not make that.

 

@bernhard I agree on using 'addHookAfter' to be sure that the method itself does not overwrite the value again.

BTW:

1 hour ago, bernhard said:

use tracy and debug $event:


wire()->addHookBefore('Page(template=user)::changed(0:last_name, 1:first_name)', function($event) {
    bd($event);
});

 

I used Tracy with the above code but it didn't debug $event:

img1.png.7d17915f8680d39f05d19744fdb1e5f3.png

However, if I use Tracy this way

wire()->addHookBefore('Pages::saveReady', function($event) {
    bd($event);
});

it debugs $event:

img2.png.062868af5760d7b59e6eea0d6d6cc9dd.png

Link to comment
Share on other sites

39 minutes ago, LAPS said:

I used Tracy with the above code but it didn't debug $event:

that's exactly why using tracy is so great, because now you know that the hook did not execute ;) it's the same for me. don't know why it is not executed. maybe it's a bug, maybe we are using the conditional hook wrong. I didn't use conditional hooks for a long time and sometimes hooks with if-statements are even easier to read. so it's totally up to you which one you use.

  • Like 1
Link to comment
Share on other sites

Did you try turning off formatting before changing the page field data?

wire()->addHookAfter('Page(template=user)::saveReady', function($event) {
    $page = $event->arguments('page');
	$page->of(false);
    $page->title = $page->last_name . " " . $page->first_name;
        $event->return = $page;
});

 

Edited by psy
Changed hook to after save ready
Link to comment
Share on other sites

47 minutes ago, psy said:

Did you try turning off formatting before changing the page field data?


wire()->addHookBefore('Page(template=user)::saveReady', function($event) {
    $page = $event->arguments('page');
	$page->of(false);
    $page->title = $page->last_name . " " . $page->first_name;
        $event->return = $page;
});

 

@psy I just tried it, and did not work.

Link to comment
Share on other sites

@LAPS hrmm... here is a similar hook that I use and it works fine:

/***** Ensure the $page->seo->title field is not empty */

wire()->addHookAfter('Pages::saveReady', function($event) {
    $page = $event->arguments(0);

    $t = wire()->templates->get($page->template);
    if($t->hasField("seo_title") && !$page->seo_title) {
        $title = $page->get('headline|title');
        $page->of(false);
        $page->seo_title = $title;
        $event->return = $page;
    }

});

 

Link to comment
Share on other sites

@LAPS I haven't used conditional hooks. Instead, I'd have written it as:

wire()->addHookAfter('Pages::saveReady', function($event) {
    $page = $event->arguments('page');
    if ($page->template != 'user') return;
    $page->of(false);
    $page->title = $page->last_name . " " . $page->first_name;
    $event->return = $page;
});

 

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...