Update page by field key

Hi there

Another nooby question maybe.
I have a situation where I loop through all my fields on page.update hook and in some cases I change the field content.

For testing purposes I set the array key manually for the field I wanted to update:
Like:

$newPage->update([  
            'teasertext' => $newBlocks->toArray(),
]);

As you can see my teasertext field is a blocks field which I update.

Now because I want to do this for all the fields I do something like:

foreach ($newPage->content()->fields() as $field) {
    $fieldKey = $field->key();
    ...
}

So my $fieldKey contains a string named teasertext in at least the case where my field is the teasertext field.

Now I want to use the same update part, but that would not work anymore…

$newPage->update([  
            $fieldKey => $newBlocks->toArray(),
          ]);

So I kinda have to use a variable as an array key…

So I thought I might use:

$updates = [];
$updates[$fieldKey] = $newBlocks->toArray();

$newPage->update($updates);

But this does not work either…
How could I update the field I am currently in (in my loop)?..

thanks for any help here. :woozy_face:

It doesn’t sound like a good idea to update each field individually inside the loop if that’s what you are trying to do. Instead, you should create your data array once inside the loop, then update the page as your last step.

Yeah I just realized exactly that, after hours of trying… :see_no_evil:
So one can’t execute the page->update() twice?

I thought I had it when testing the second blocks field. Then tried in the first again and it did not work anymore.
Then I went a few steps back and finally realized that only the second block fields got the updates…
:see_no_evil: :see_no_evil: :see_no_evil: :see_no_evil: :see_no_evil:

<?php

Kirby::plugin('seriamlo/mh-image-block', [
  'hooks' => [
    'page.update:after' => function ($newPage, $oldPage) {

      $updatedBlockFields = [];

      foreach ($newPage->content()->fields() as $field) {
        // there is no method to get the fields type
        // except by getting the pages blueprint and looking for the fields key
        // https://forum.getkirby.com/t/how-to-determine-field-type-in-custom-field-method/19254
        $fieldKey = $field->key(); // name of the field, like 'teasertext'

        // https://getkirby.com/docs/reference/objects/cms/page-blueprint/field
        $fieldDefinition = $newPage->blueprint()->field($fieldKey);

        if (isset($fieldDefinition['type']) && $fieldDefinition['type'] === 'blocks') { // some field definitions dont have a type 🤷‍♂️
          $newBlocks = new Kirby\Cms\Blocks();
          $blocks = $newPage->content()->get($fieldKey)->toBlocks();

          foreach ($blocks as $block) {
              if ($block->type() !== 'image') {
                  $newBlocks->add($block);
              } else {
                  $url      = $block->image()->toFile()->url();
                  $images   = $block->image()->toFiles()->pluck('filename');
                  $newBlock = new \Kirby\Cms\Block(
                      [
                  "content" => [
                    'location' => 'kirby',
                    'image'    => $images,
                    'alt'      => $block->alt()->value(),
                    'caption'  => $block->caption()->value(),
                    'url'      => $url,
                    'link'     => $block->link()->value(),
                  ],
                  'id'   => $block->id(),
                  'type' => $block->type()
                ],
                  );
                  $newBlocks->add($newBlock);
              }
          }

          $updatedBlockFields[$fieldKey] = $newBlocks->toArray();
        }
      }

      // update once!
      $newPage->update($updatedBlockFields);
    }
  ]
]);

But thank you a lot for your help.
I am getting super desperate :joy:

Right, since the update function triggers the update hook, you would end up in a loop.