0

I have some D8 entity code that does read-modify-write on a multivalue entity-reference field. The modification required is to change references to one entity to refer to another, without changing other references.

I get an exception thrown in $entity->set(...) saying that the Value is not an entity. I presume I'm calling the wrong thin somewhere but I don't see what the correct call pattern would be.

What I have at present is, and here $field_values is a EntityReferenceFieldItemList:

  $field = '...';
  $entity = $storage->load(...);

  $field_values = $entity->{$field};
  foreach ($field_values as $k => &$item) {
    $target_id = $item->get('target_id')->getValue();
    if ($target_id === $old_value->id()) {
      $changed = TRUE;
      $item->set('target_id', $new_value);
    }
  }
  if ($changed) {
    var_dump($field_values);
    $entity->set($field, $field_values);
    $entity->save();
  }

where $old_value and $new_value are both EntityInterface objects and $field_values is an EntityReferenceFieldItemList.

1 Answer 1

1
  foreach (entity->get($field) as $k => $item) {
    $target_id = $item->target_id;
    if ($target_id == $old_value->id()) {
      $changed = TRUE;
      $item->target_id = $new_value;
    }
  }

  if ($changed) {
    $entity->save();
  }

That's it. You don't need to set any values, they are objects, your loop already updates them. You also don't need to loop over it by reference.

I just simplified it a bit because you can access target_id as a property through __set() and __get(), which has the advantage that you directly get the value and don't need to call getValue() on it.

See https://wizzlern.nl/drupal/drupal-8-entity-cheat-sheet for more information for example.

1
  • 1
    One more note, I removed the strict check (===), the entity API doesn't guarantee scalar types, values are loaded from the database and by default are strings, but if set somehow by code, it might be an integer.
    – Berdir
    Jun 28, 2018 at 18:16

Your Answer

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

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