1

I have a custom FieldItem that has a single 'value' property that is also a custom TypedData.

This TypedData property holds an object. The \Drupal\Core\TypedData\TypedDataInterface::getValue() on the property(TypedData) returns a string fetched from the represented object and \Drupal\Core\TypedData\PrimitiveInterface::getCastedValue() returns the represented object.

All is working fine but one thing. In my entity which has this FieldItem attached, I update its value in the entity::preSave() operation.

And Drupal started to complain Notice: Object of class ... could not be converted to int in drupal_schema_get_field_value().

And I couldn't figure out why was the represented object used instead of the "plain" value.

After a bit of debugging I have found that when I set the FieldItem's value(I pass an object) in the entity::preSave() the FieldItem's properties are not loaded which will cause the \Drupal\Core\Field\FieldItemBase::__get() fetching the value from FieldItem values array instead of getting it from properties.

Any idea why the properties are not loaded? I was thinking that it has something to do with performance maybe but since the field item is just a wrapper around data types it makes no sense that field item would handle the data itself.

Edit: Looking more closely at entity values and properties it seems that only computed properties are initialized by default. But real properties are initialized only when \Drupal\Core\TypedData\Plugin\DataType\Map::get() is called. The values are meant for plain values when creating a new entity for example, if I understand it correctly, but I don't get why the properties are not utilized yet.

1 Answer 1

0

I will answer my own question...

I am not sure when the property initialization comes to play but adding this code into my field item solved it. The get method will look for the property and initialize it if it does not exists with existing value which will result in the field returning correct data.

  /**
   * {@inheritdoc}
   */
  public function preSave() {
    $this->get('value');
  }

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.