# Programatically update blocks in a layout

**URL:** https://forum.getkirby.com/t/programatically-update-blocks-in-a-layout/25790
**Category:** Questions
**Tags:** v3
**Created:** [June 23, 2022, 1:04am UTC](https://forum.getkirby.com/t/programatically-update-blocks-in-a-layout/25790 "2022-06-23T01:04:19Z")
**Posts on this page:** 1
**Showing post:** 8

<div class="post-metadata">

### Author: ![afincato](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/afincato/32/3446_2.png) [@afincato](https://forum.getkirby.com/u/afincato)
#### Post date: [November 7, 2022, 5:50pm UTC](https://forum.getkirby.com/t/programatically-update-blocks-in-a-layout/25790/8 "2022-11-07T17:50:19Z")

</div>

Hi @Moucky and super thanks for this thread and sharing your WIP code! It helped me immensely, and in fact I managed to do something similar for my own use case.

What I needed to do was to replace a bunch of HTML inside a builder field with different type of blocks, some of which are custom blocks of type column ([GitHub - youngcut/kirby-column-blocks: Use columns in block fields based on the layout field.](https://github.com/youngcut/kirby-column-blocks)). I had to:

- loop over all blocks and update type text blocks, as well as, loop over sub-blocks inside columns block and update possible text block inside there
- reconstruct the whole builder block data structure, including the columns type block
- update the builder field of the page

I got really stuck trying to understand how to put back the custom columns block, which uses the layout feature. At the end, it was thanks to your code that I discovered the `Kirby\Cms\LayoutColum` method. After that I realised I had to wrap the layout object inside a new block and all worked together. Following my code, in the hope it would be useful to you and anybody else here in the forum.

```auto
$updatedBlocks = [];

foreach($blocks as $block) {

    $blockType = $block->type();

    if ($blockType === 'columns') {

        // we have one layout per block, no need to loop over
        $layout = $block->layout()->toLayouts()->first();

        $columnsNew = [];
        foreach($layout->columns() as $column) {
            // we need to:
            // - parse the layout blocks
            // - reconstruct the layout with updated blocks
            // - convert it back to a layout object

            $subblocks = $column->blocks();
            $updatedSubblocks = parseBlocks($subblocks, $client, 'layout');
            $subblocksNew = new Kirby\Cms\Blocks($updatedSubblocks);

            $columnNew = new Kirby\Cms\LayoutColumn(
                [
                    'blocks' => $subblocksNew->toArray(),
                    'width' => $column->width(),
                ]
            );

            array_push($columnsNew, $columnNew);
        };

        $layoutColumnsNew = new Kirby\Cms\LayoutColumns($columnsNew);
        
        $layoutNew = Kirby\Cms\Layout::factory([
            'columns' => $layoutColumnsNew->toArray(),
        ]);

        $layoutsNew = new Kirby\Cms\Layouts([$layoutNew]);

        // -- update block
        $blockLayoutUpdated = [
            'content' => [
                'layout' => $layoutsNew->toArray(),
            ],
            'type' => 'columns',
        ];

        $blockLayoutNew = new Kirby\Cms\Block($blockLayoutUpdated);
        array_push($updatedBlocks, $blockLayoutNew);

    } else if ($blockType === 'text') {

        // custom code to update block-text
       // [...]
        // -- update block
        $blockUpdated = [
            'content' => [
                'text' => $text_new,
                'footnotes' => $footnotes_new,
            ],
            'type' => $block->type(),
        ];

        $blockUpdated = new Kirby\Cms\Block($blockUpdated);
        array_push($updatedBlocks, $blockUpdated);

    } else {
        array_push($updatedBlocks, $block);
    }

}; // -- end blocks foreach

```

- `parseBlocks()` is the function you see above, which is used in a recursive manner to map over the blocks inside the columns block (each columns block has x-number of columns, each with a block)
- the important steps to reconstruct a block with a layout / columns inside, are:
  - `new Kirby\Cms\LayoutColumn()`
  - `new Kirby\Cms\LayoutColumns()`
  - `Kirby\Cms\Layout::factory()`
  - `new Kirby\Cms\Layouts()`
  - check the code snippet above for more details, arguments, etc

One you get the data in the `$updatedBlocks` array, here’s how I updated the builder field:

```auto
$blocksNew = new Kirby\Cms\Blocks($updatedBlocks);

// -- write to file
kirby()->impersonate('kirby');
$newPage->update([
  'builder' => json_encode($blocksNew->toArray()),
]);

```

Tested with Kirby `7.4` and `8.1`.

---

_[View the full topic](https://forum.getkirby.com/t/programatically-update-blocks-in-a-layout/25790)._
