How to programmatically insert and update Field Collection values? I would like to insert and update Field Collection values. I'm using Drupal 8 with field_collection 8.x-1.0-alpha1.

Setup

I have created a new content type test_content_type with the following fields:


Title
Body
…
Test Field Collection


Machine name: field_test_field_collection
Type: field collection



The field collection field_test_field_collection has only one field:


Example Text


Machine name: field_text
Type: text



The Problem

I also created a node with values, for instance Lorem Ipsum as field_text.value, but I don't know how to read and define the value programmatically. I tried the following, which updates body but doesn't update field_text:

&lt;?php

namespace Drupal\my_module\Controller;

use Drupal;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityStorageInterface;

class FieldCollectionTestController extends ControllerBase {
    /**
     * @return array
     */
    public function content() {
        $nodeId = 1402;

        /** @var EntityStorageInterface $entityStorage */
        $entityStorage = Drupal::entityTypeManager()-&gt;getStorage('node');
        $node = $entityStorage-&gt;load($nodeId);

        // Dump.
        {
            ob_start();
            var_dump($node-&gt;field_test_field_collection-&gt;field_text);
            $dump = ob_get_clean();
        }

        // Update node and field collection.
        {
            $exampleText = "Updated at " . time();

            $node-&gt;body = $exampleText;
            $node-&gt;field_test_field_collection-&gt;field_text = $exampleText;

            $node-&gt;save();
        }

        $response = [
            '#theme' =&gt; 'item_list',
            '#title' =&gt; 'Dumps',
            '#items' =&gt; [
                [
                    '#type' =&gt; 'markup',
                    '#markup' =&gt; $dump,
                ],
            ],
        ];

        return $response;
    }
}


The value of $dump is null.

Question

How do you insert, update and delete Field Collections in Drupal 8?
The following snippet (compatible with field_collection 8.x-1.0-alpha1) reuses an existing FieldCollectionItem or creates a new one on demand. The last few lines show how to modify fields inside the FieldCollectionItem.

If one has a field collection with a different name, then it should be enough to replace all occurrences of field_test_field_collection with the custom field collection's machine name.

&lt;?php

// […]

$nodeId = 123;

/** @var EntityStorageInterface $entityStorage */
$entityStorage = Drupal::entityTypeManager()-&gt;getStorage('node');

$node = $entityStorage-&gt;load($nodeId);
$node-&gt;body = 'Body Update: ' . date('c');

/** @var Drupal\Core\Field\FieldItemList $fieldItemList */
$fieldItemList = $node-&gt;field_test_field_collection;

// Reuse existing Field Collection.
if (count($fieldItemList))
{
    /** @var \Drupal\field_collection\Plugin\Field\FieldType\FieldCollection $fieldCollection */
    $fieldCollection = $fieldItemList[0];
    $fieldCollectionItem = FieldCollectionItem::load($fieldCollection-&gt;value);
}

// Create new Field Collection.
else
{
    $fieldCollectionItem = FieldCollectionItem::create([
        'field_name' =&gt; 'field_test_field_collection',
    ]);

    $fieldCollectionItem-&gt;setHostEntity($node);

    $node-&gt;field_test_field_collection[] = [
        'field_collection_item' =&gt; $fieldCollectionItem,
    ];
}

$fieldCollectionItem-&gt;set('field_text', 'Last Update: ' . date('c'));

$node-&gt;save();


Deleting an existing collection is as simple as: fieldCollectionItem-&gt;delete();

Please have a look at the source code of the unit test class Drupal\field_collection\Tests\FieldCollectionBasicTestCase for more information.