<p>You shouldn't JSON-encode the table field values; Craft handles that internally. Simply give it a multi-dimensional array.</p>
<p>The below would save one row with two columns to the table field <code>itemEvents</code>, belonging to an element <code>$match</code>:</p>
<pre class="lang-php prettyprint-override"><code>$itemsTable = [[
    'col1' =&gt; $itemType,
    'col2' =&gt; $itemTime,
]];

$match-&gt;setFieldValue('itemEvents', $itemsTable);

...

\Craft::$app-&gt;getElements()-&gt;saveElement($match);
</code></pre>

CC BY-SA 4.0
2023-01-15T01:38:44.580Z
Thanks for this one too! I saw some other answers saying it needed to be JSON-encoded, thanks for clarifying. I have a question about the last line of saving the element; I'm using `Event::on(Entry::class,Element::EVENT_BEFORE_SAVE,` (and have tried `EVENT_AFTER_SAVE` too) for this and it seems to create an infinite loop. Any advice on how to do that properly?
supazu
CC BY-SA 4.0
2023-01-15T13:59:51.637Z
@brynli64 Right, you shouldn't explicitly save the entry (using `\Craft::$app->getElements->saveElement()` in an `EVENT_BEFORE_SAVE` or `EVENT_AFTER_SAVE` event handler. In this case, you probably want to use the `EVENT_BEFORE_SAVE` event handler, and just `$match->setFieldValue('itemEvents', $itemsTable);` inside that (assuming `$match` is the entry being saved). The complicating factor is that the source for your table is in a Matrix block; I'm not sure if that data is even available before the entry has been saved (Matrix blocks are saved as separate elements).
Mats Mikkel Rummelhoff
CC BY-SA 4.0
2023-01-17T06:11:17.183Z
Thanks for the info! I'll look into that a bit more then.
supazu
CC BY-SA 4.0
2023-01-17T06:20:36.523Z
So it's actually working with `EVENT_BEFORE_SAVE` now, however, it's only adding one row (presumably it's going throw each row and overwriting the previous one.) Any thoughts on how I can just add a row, rather than resave the whole table? Apologies for the trouble, I appreciate your help!
supazu
CC BY-SA 4.0
2023-01-17T08:33:25.087Z
@brynli64 Great! The table field returns an array, so if you want to add new rows without overwriting existing data, you'll need to push or merge the new rows to the array the field returns. I.e. something like `$match->setFieldValue('itemEvents', array_merge($match->itemEvents ?? [], $itemsTable));`
Mats Mikkel Rummelhoff
CC BY-SA 4.0
2023-01-17T12:19:22.757Z
Brilliant - I think that's done it! Thank you!
supazu
CC BY-SA 4.0
2023-01-14T20:48:39.150Z
2023-01-14T20:48:39.150Z
Mats Mikkel Rummelhoff
<p>I'm having some trouble adding a row to a table field programmatically. I'm iterating over a table inside a Matrix field and would like to save those values to another table (if that makes sense.)</p>
<pre><code>foreach ($blocks as $block) {
    $items = $block-&gt;items;
    foreach ($items as $item) {
        $itemType = $itemEvents['type'];
        $itemTime = $itemEvents['time'];
        $itemsTable = array(
            array(
                'col2' =&gt; $itemType,
                'col3' =&gt; $itemTime,
            )
        );
    }
    
    ## I understand this is wrong, but this is what I want to do:
    $match-&gt;setFieldValue('itemEvents', json_encode($itemsTable));
}
</code></pre>
<p>Can anyone help with the last part of actually updating the <code>itemEvents</code> table field/adding a row to it?</p>

<modules><table-field>
Add rows to table field
# Add rows to table field

(Asked by: username_0 on 2023-01-14)

I'm having some trouble adding a row to a table field programmatically. I'm iterating over a table inside a Matrix field and would like to save those values to another table (if that makes sense.)
foreach ($blocks as $block) {
    $items = $block->items;
    foreach ($items as $item) {
        $itemType = $itemEvents['type'];
        $itemTime = $itemEvents['time'];
        $itemsTable = array(
            array(
                'col2' => $itemType,
                'col3' => $itemTime,
            )
        );
    }
    
    ## I understand this is wrong, but this is what I want to do:
    $match->setFieldValue('itemEvents', json_encode($itemsTable));
}

Can anyone help with the last part of actually updating the itemEvents table field/adding a row to it?

**Tags:** modules, table-field


---

## 1 answers

### Answer by username_1 on 2023-01-14. Score: 2 | Accepted answer

You shouldn't JSON-encode the table field values; Craft handles that internally. Simply give it a multi-dimensional array.
The below would save one row with two columns to the table field itemEvents, belonging to an element $match:
$itemsTable = [[
    'col1' => $itemType,
    'col2' => $itemTime,
]];

$match->setFieldValue('itemEvents', $itemsTable);

...

\Craft::$app->getElements()->saveElement($match);

> **Comments:**
> **username_0**: Thanks for this one too! I saw some other answers saying it needed to be JSON-encoded, thanks for clarifying. I have a question about the last line of saving the element; I'm using `Event::on(Entry::class,Element::EVENT_BEFORE_SAVE,` (and have tried `EVENT_AFTER_SAVE` too) for this and it seems to create an infinite loop. Any advice on how to do that properly?  
> **username_1**: @brynli64 Right, you shouldn't explicitly save the entry (using `\Craft::$app->getElements->saveElement()` in an `EVENT_BEFORE_SAVE` or `EVENT_AFTER_SAVE` event handler. In this case, you probably want to use the `EVENT_BEFORE_SAVE` event handler, and just `$match->setFieldValue('itemEvents', $itemsTable);` inside that (assuming `$match` is the entry being saved). The complicating factor is that the source for your table is in a Matrix block; I'm not sure if that data is even available before the entry has been saved (Matrix blocks are saved as separate elements).  
> **username_0**: Thanks for the info! I'll look into that a bit more then.  
> **username_0**: So it's actually working with `EVENT_BEFORE_SAVE` now, however, it's only adding one row (presumably it's going throw each row and overwriting the previous one.) Any thoughts on how I can just add a row, rather than resave the whole table? Apologies for the trouble, I appreciate your help!  
> **username_1**: @brynli64 Great! The table field returns an array, so if you want to add new rows without overwriting existing data, you'll need to push or merge the new rows to the array the field returns. I.e. something like `$match->setFieldValue('itemEvents', array_merge($match->itemEvents ?? [], $itemsTable));`  
> **username_0**: Brilliant - I think that's done it! Thank you!  

---

