16

How can you programmatically save an entry that has a Matrix field in Craft 3?

(Something like this gist for Craft 2)

2 Answers 2

24

Saving Matrix fields programmatically got a lot easier in Craft 3 thanks to all the content refactoring.

use craft\elements\Entry;
use craft\elements\MatrixBlock;

// Figure out the section & entry type
$section = Craft::$app->sections->getSectionByHandle('news');
$entryTypes = $section->getEntryTypes();
$entryType = reset($entryTypes);

// Create an entry
$entry = new Entry([
    'sectionId' => $section->id,
    'typeId' => $entryType->id,
    'fieldLayoutId' => $entryType->fieldLayoutId,
    'authorId' => 1,
    'title' => 'My Entry',
    'slug' => 'my-entry',
    'postDate' => new DateTime(),
]);

// Set the custom field values (including Matrix)
$entry->setFieldValues([
    'summary' => 'Some "summary" custom field value...',
    'matrixField' => [
        'new1' => [
            'type' => 'blockTypeHandle',
            'fields' => [
                // the block's custom field values...
            ],
        ],
        'new2' => [
            'type' => 'blockTypeHandle',
            'fields' => [
                // the block's custom field values...
            ],
        ],
    ],
]);

// Save the entry
Craft::$app->elements->saveElement($entry);
1
  • 2
    👍 That still works in Craft CMS 4 (as of writing I am using 4.4.x). Just in case someone is asking if that's only a Craft 3 thing. :)
    – Arvid
    May 10, 2023 at 13:00
13

Just an additional note:

If you want to append certain elements to your matrix field instead of overwriting them all you have to do

Update Craft 4.0

there is a new sortOrder key that makes my previous answer obsolete.

// grab all existing ids
$existingIds = $element->getFieldValue('matrixField')->ids();
// add a new block to the ids
$existingIds[] = 'new1';

$element->setFieldValue('matrixField', [
    'sortOrder' => $existingIds,
    'blocks' => [
        'new1' => [
            'type' => 'blockTypeHandle',
            'fields' => [
                // the blocks custom field values...
            ]
        ]
    ]
]);
// Save the entry
Craft::$app->elements->saveElement($element);

Old answer for Craft 3 (first versions < 3.6)

Just an additional note:

If you want to append certain elements to your matrix field instead of overwriting them all you have to do

/** @var \craft\fields\Matrix $field */
$field = Craft::$app->getFields()->getFieldByHandle('matrixField');

// get the existing matrixField Value, keep in mind, this is a Query and not an array
$existingMatrixQuery = $element->getFieldValue('matrixField');

// serialize the data in order to get an array like Brandon Kelly
// created in his answer
$serializedMatrix = $field->serializeValue($existingMatrixQuery, $element);

// append the new blocks to the existing array
$serializedMatrix['new1'] = [
    'type' => 'blockTypeHandle',
    'fields' => [
        // the block's custom field values...
    ]
];

$element->setFieldValue('matrixField', $serializedMatrix);

// Save the entry
Craft::$app->elements->saveElement($element);
1
  • This is perfect, thanks Robin! It's icing on the cake that Brandon has baked. :)
    – Lindsey D
    Sep 1, 2019 at 5:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.