# How to change page content in \`page.update.before\` hook?

**URL:** <https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483>\
**Category:** Questions\
**Tags:** v3\
**Created:** [March 21, 2019, 8:39am UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483 "2019-03-21T08:39:13Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![hdodov](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/hdodov/32/8171_2.png) [@hdodov](https://forum.getkirby.com/u/hdodov)\
**Post date:** [March 21, 2019, 8:39am UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483/1 "2019-03-21T08:39:13Z")

</div>

I’m developing a plugin that adds IDs to structure field entries. However, I have trouble saving the modified data. Here’s my plugin hook:

```auto
'hooks' => [
  'page.update:before' => function ($page, $values, $strings) {
    foreach ($values as $key => $field) {
      if (is_array($field)) {
        fillIds($field);

        $page->update([
          $key => yaml::encode($field)
        ]);
      }
    }

    $values['test'] = 'foo1'; // does nothing
    $strings['test'] = 'foo2'; // does nothing

    return [
      'test' => 'foo3' // does nothing
    ];
  }
]

```

As you can see, I try 4 ways of updating the page. If I call `$page->update()`, it does nothing, probably because Kirby detects it would cause and endless loop due to the hook? If I change the $values and $strings array, nothing happens (I tried specifying them as references in the arguments but I get errors). Finally, if I return an array, still nothing happens.

How am I supposed to update the page? I could use `page.update.after` but I think it would be less efficient. Also, I don’t get the `$values` arguments which is not so convenient.

@texnixe has built [a similar plugin](https://github.com/texnixe/kirby-structure-id/blob/master/kirby-structure-id.php#L133) for Kirby 2 and it uses the `$page->update()` method. That does work in `page.update.after`, but not in `page.update.before` where I need it.

How do I update the page content in `page.update.before`?

---

<div class="post-metadata">

**Author:** ![lukaskleinschmidt](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/lukaskleinschmidt/32/13388_2.png) [@lukaskleinschmidt](https://forum.getkirby.com/u/lukaskleinschmidt)\
**Post date:** [March 21, 2019, 9:04am UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483/2 "2019-03-21T09:04:33Z")

</div>

Before hooks do not let you modify the incoming data. They give you the option to do something before the values are actually saved to disk. Like intervening the save action by `throw new Error('Oops')` or perhaps clear a cache. In your case you would probably need to use the `page.update:after` hook and update any structure item that does not have an id yet in there.

---

<div class="post-metadata">

**Author:** ![Microman](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/microman/32/15876_2.png) [@Microman](https://forum.getkirby.com/u/Microman)\
**Post date:** [February 11, 2023, 11:53pm UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483/3 "2023-02-11T23:53:00Z")

</div>

You can do it. Edit the content and fire  
`$page->update($your_edited_content)`

In my experience, you even can’t fall into a endless loop with that…

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 12, 2023, 9:19am UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483/4 "2023-02-12T09:19:47Z")

</div>

> [@Microman](#):
>
> You can do it.

You can do what? Not sure what you are trying to add here?

---

<div class="post-metadata">

**Author:** ![Microman](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/microman/32/15876_2.png) [@Microman](https://forum.getkirby.com/u/Microman)\
**Post date:** [February 12, 2023, 2:14pm UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483/5 "2023-02-12T14:14:58Z")

</div>

Nevermind. I’ve tried in `page.update.after`. So as @hdodov mentioned, it works there…

---

<div class="post-metadata">

**Author:** ![leo\_portatour](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/leo_portatour/32/15515_2.png) [@leo\_portatour](https://forum.getkirby.com/u/leo_portatour)\
**Post date:** [April 10, 2026, 2:49pm UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483/6 "2026-04-10T14:49:06Z")

</div>

Hi @texnixe , I have a similar case and I think it is valid in general.

I want to modify field values before they get saved. My application case is that I analyze the contents of layouts and see if a certain block was used that needs a certain css and then store with the page that this page should always include a specific css when rendering (but only when this block type is used). So the field I modify on the page is called ‘usedblocktypes’

I do not want to “save the page twice” with an page.update:after hook. That would be ugly, as it would cost me CPU. Why do two commits() if one is enough?

I am used from other systems (SQL Servers, Dynamics CRM, …) to have hooks that can run before saving a database entry that can manipulate the in-memory entry. I expect that this “just works”, so I wondered how it works with Kirby.

I debugged deeply into the page.update:before hook and found:

> **[page.update:before](https://getkirby.com/docs/reference/plugins/hooks/page-update-before)**
>
> Reference page for the hook page.update:before

```  
‘hooks’ =\> [  
‘page.update:before’ =\> function (Kirby\Cms\Page $page, array $values, array $strings) {  
// your code goes here  
}  
]  
```

- all input variables are passed by value, not by reference. So manipulating $strings or $values won’t change the values going into storage
- the hook can actually return a maniplated $page entity, this will be parsed. I found no obvious idea how to pass the new input into this.
- the ModelCommit→call(array $arguments, Closure $callback) is responsible to call the hook, but I found no way how I can pass modified $arguments. I didn’t try manipulating $hook though, maybe that is the answer

… so I found no way to do this using the page.update:before hook.

The stacktrace during debugging showed me that I am within Kirby\Cms\Page→public function update( ?array $input = null, ?string $languageCode = null, bool $validate = false ): static

So I override that update() function on a model in site/models/default.php

```

````auto
public function update( ?array $input = null, ?string $languageCode = null, bool $validate = false ): static {
    if ($input) {
       $this->hookPageUpdateBefore($input);
    }
    return parent::update($input, $languageCode, $validate);
}

public function hookPageUpdateBefore(array &$input) {
  $input['usedblocktypes'] = 'whatever';
}

```

````

What is the “correct Kirby way” ?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [April 10, 2026, 6:21pm UTC](https://forum.getkirby.com/t/how-to-change-page-content-in-page-update-before-hook/13483/7 "2026-04-10T18:21:38Z")

</div>

The hook doesn’t really make sense here, but overriding the `update` method does.
