LAPS Posted December 21, 2017 Share Posted December 21, 2017 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 More sharing options...
bernhard Posted December 21, 2017 Share Posted December 21, 2017 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: 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. 3 Link to comment Share on other sites More sharing options...
LAPS Posted December 21, 2017 Author Share Posted December 21, 2017 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. 1 Link to comment Share on other sites More sharing options...
bernhard Posted December 21, 2017 Share Posted December 21, 2017 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... 1 Link to comment Share on other sites More sharing options...
LAPS Posted December 21, 2017 Author Share Posted December 21, 2017 27 minutes ago, bernhard said: [...] 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 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 More sharing options...
bernhard Posted December 21, 2017 Share Posted December 21, 2017 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 More sharing options...
LAPS Posted December 21, 2017 Author Share Posted December 21, 2017 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 More sharing options...
bernhard Posted December 21, 2017 Share Posted December 21, 2017 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. 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. 1 Link to comment Share on other sites More sharing options...
Soma Posted December 21, 2017 Share Posted December 21, 2017 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; }); 2 Link to comment Share on other sites More sharing options...
LAPS Posted December 21, 2017 Author Share Posted December 21, 2017 @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: However, if I use Tracy this way wire()->addHookBefore('Pages::saveReady', function($event) { bd($event); }); it debugs $event: Link to comment Share on other sites More sharing options...
bernhard Posted December 21, 2017 Share Posted December 21, 2017 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. 1 Link to comment Share on other sites More sharing options...
psy Posted December 21, 2017 Share Posted December 21, 2017 (edited) 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 December 21, 2017 by psy Changed hook to after save ready Link to comment Share on other sites More sharing options...
LAPS Posted December 21, 2017 Author Share Posted December 21, 2017 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 More sharing options...
psy Posted December 21, 2017 Share Posted December 21, 2017 @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 More sharing options...
psy Posted December 21, 2017 Share Posted December 21, 2017 @LAPS just noticed you have Page('template=user')::saveReady. Try changing it to Pages('template=user')::saveReady - ie Pages, not Page Link to comment Share on other sites More sharing options...
LAPS Posted December 21, 2017 Author Share Posted December 21, 2017 25 minutes ago, psy said: @LAPS just noticed you have Page('template=user')::saveReady. Try changing it to Pages('template=user')::saveReady - ie Pages, not Page It did not work, also by using Pages('template=user')::saveReady. Link to comment Share on other sites More sharing options...
psy Posted December 21, 2017 Share Posted December 21, 2017 @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; }); 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now