Jump to content

"Add hook after save" and create child page, but do nothing after further saves

Recommended Posts

So I have been diving into hooks lately, and I am enjoying them thus far. However, I guess I am a bit stumped on how to achieve what I want too. I am trying to set up a hook that would create a new child page when the parent page is saved. However, when you save the parent page a second time, I just need to update the child page without creating multiple child pages. What would be the best way to go about this?

So after rereading my post, I believe it is a bit vague so I will try to explain more. 

The Goal:

  1. Create a page with a template "one".
  2. Once the page is created/saved => create a new child page with the template of "two"
  3. If the parent is saved anytime after, do nothing to the child page (limit the parent page to one child page)

The parent page is really just being used to output content, whereas the child page is being used to pull out the some fields from the parent to be used elsewhere. I might have made this too complicated in my head.

Edited by louisstephens
Trying to provide more clarification.

Share this post

Link to post
Share on other sites

If I understand correctly, something  like this should work, let us know if you need more detail: 

wire()->addHookekAfter("Pages:saved", function($e){
	$page = $e->arguments(0);
	if($page->template == "one"){
		$pageTwo = $page->child("template=two");
			//create child page code and save!


  • Like 3

Share this post

Link to post
Share on other sites
12 hours ago, louisstephens said:

So I have been diving into hooks lately, and I am enjoying them thus far.

Better late than never 😉 😛 

You can use Pages::added for this: https://processwire.com/api/ref/pages/added/

And using conditional hooks (https://processwire.com/blog/posts/new-ajax-driven-inputs-conditional-hooks-template-family-settings-and-more/#new-conditional-hooks) it gets even easier and cleaner:

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

I always start with the basic hook and test it. In this case this was quite interesting, because it fired twice! The reason is that this page contains a repeater matrix that creates a page for the first (possible) item:


Then you can modify the hook to be more specific:

$wire->addHookAfter('Pages::added(template=basic-page)', function(HookEvent $event) {
  $page = $event->arguments(0);

Voila, it fires on the right page only:


And it will not fire on any further publish/save/etc events 😉 

  • Like 5

Share this post

Link to post
Share on other sites

Thanks @bernhard! That was exactly what I was looking for. Now I'll continue down the path of learning hooks, and hopefully stop making mistakes like:

$p = new Page();
$u->template = "scripts";
$u->parent = wire('pages')->get($page->id);
$u->title = "Test";
$u->name = "test";

Which obviously just blows up in your face.😅

  • Like 1

Share this post

Link to post
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 quickjeff
      Hi Guys, 
      I have been debugging a site for the last 2 hours and cannot solve the issue. 
      I have a site running on 3.0.148. 
      I installed the Kongondo Blog module and was updating the templates to include the website style. 
      Once everything was set and done, I checked the page tree to see an error appear. 
      Template must be assigned a name before 'filename' can be accessed
      The same error appears in templates. 
      Debugging Steps
      I checked the templates in the server to ensure I didnt accidentally delete the namespace.  Deleted cache in browser and server under assets Still no go. 
      Any help is appreciated. 
    • 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!

    • By celfred
      Here's what I'm trying to achieve : I have a textarea field that is frontend editable on any page I want to. If a user with a specific role updates it, I want to tick a checkbox field on the parent page where the textarea resides. So I tried to hook as follows in my ready.php file :

        $this->addHookBefore('Fieldtype::savePageField', function(HookEvent $event) {       $page = $event->argument[0];       $field = $event->argument[1];       if($this->user->hasRole('teacher')) {      $page->alertBox = 1;       } // DEBUG HERE (bd($page),  l($field)... ????   }); Of course (!) it doesn't work (yet !) but the thing is I have no idea how to debug this since my bd() never triggers. I've tried the 'Event interceptor' of Tracy debugger which helped me setting up my hook. I guess my $page and $field are correct... but how could I go any further ?
      The road is long to become a dev (when you're not one 🙂 )...
      For further information in case someone wonders : I'd like to set up a textarea that is modified by a user (having a 'player' role, ie 'student'). When front-end modified, I wish it would automatically alert me (the teacher) by ticking a box. So when I log in with my teacher role, I get a list of all textareas I have to read over. When I read/correct/update them (front-end), I would like my hook to automatically untick the box to remove it from my list. In other words, the 'textarea' status should go back and forth according to who modified it last. For the time being, I have managed to make it work with a checkbox that the user has to manually tick/untick, but I've noticed many kids forget to tick the box so they edit their text and I don't get a notice 😞
      Thanks if anyone takes time to try and help me on that one !
    • By celfred
      I'm struggling with hooks to try and do this : adding user page to a page field when visiting a particular page on my website. In fact, I want to have a list of connected users on a particular page (called meeting-hall).
      I've tried all kinds of things (which I don't really understand, sorry) but the latest is this :

        $wire->addHookBefore('Page::render', function($e) {     $page = $e->arguments(0);     if ($page->is("name=meeting-hall")) {       $page->connected->add($user); // connected is a Page field       $page->save();     } else {       $meeting = wire("pages")->get("name=meeting-hall");       $meeting->connected->remove($user);       $meeting->save();     }   }); I put this in my _init.php file but nothing works...
      The best I managed was updating my 'connected' field when the user loads the 'meeting hall' page by having this on the page template :

          if ($user->isLoggedin()) {       $page->connected->add($user);       $page->of(false);       $page->save();       $page->of(true);     } But I wanted to remove the user when he or she leaves the page... hence my thought about using hooks...
      If you can give me a hint, I'd greatly appreciate !
  • Create New...