Dynamically update fields with loop

Hi. I’m attempting to dynamically update page fields when a page is saved. Instead of manually updating each field I’m using a loop, but the page is only updating the last item in the loop. This behavior is confusing, maybe there’s some magical Kirby thing happening that I need to be aware of. Let me provide some simplified code examples…

My plugin…

<?php 
Kirby::plugin('twp/my-plugin', [
  'hooks' => [
    'page.update:after' => function($newPage, $oldPage){
      if($newPage->intendedTemplate() == "my-template"):
        
        // define space types
        $my_spaces = array('x_space', 'y_space', 'z_space');
        
        // loop through each space and clear its min/max fields
        foreach($my_spaces as $my_space):
          $newPage->update([
            $my_space.'_min' => '',
            $my_space.'_max' => '',
          ]);
        endforeach;
      endif;
    }
  ]
]);

My blueprint…

x_space_min:
  type: hidden
x_space_max:
  type: hidden
y_space_min:
  type: hidden
y_space_max:
  type: hidden
z_space_min:
  type: hidden
z_space_max:
  type: hidden

I figured it would roll through each min max for each ‘space type’ and clear it’s value, but it’s only clearing the last space type, z_space_min, z_space_max.

It’s as if $newPage->update overrides the previous call and expects all fields to be handled in one round. Looping through like this isn’t possible. this Any insight?

Calling update() on each field doesn’t really make much sense and won’t perform well.

There is nothing to gain from your loop, so just do it like this:



          $newPage->update([
            'x_space_min' => '',
            'x_space_max' => '',
            'y_space_min' => '',
            'y_space_max' => '',
            'z_space_min' => '',
            'z_space_max' => '',
          ]);

Hi @texnixe, Thanks for the reply.

I agree, in this simplified example, the loop is barely advantageous, but if there were many more space types each with their own min and max field it starts becoming more valuable which is the case in my current project.

So instead of dynamically calling update() repeatedly we could build an array with all the field names and values like this…

<?php 
Kirby::plugin('twp/my-plugin', [
  'hooks' => [
    'page.update:after' => function($newPage, $oldPage){
      if($newPage->intendedTemplate() == "my-template"):
        
        // Define space types
        $my_spaces = array('x_space', 'y_space', 'z_space');
        
        // Build array of fields and their updated values
        $fields = array();
        foreach($my_spaces as $my_space):
          $fields += [$my_space.'_min' => ''];
          $fields += [$my_space.'_max' => ''];
        endforeach;
        
        // Update fields
        $newPage->update($fields);

      endif;
    }
  ]
]);

Yes, of course. For the six fields I would’ve said it’s not worth it, but the important message here is to create one array and update only once.

Right, because it seems like even if you didn’t care about performance and you wanted to use update() in a loop it won’t work as expected. It’s as if update() overrides the previous call. So, yes. It can only be called once but not only for performance reasons.