I created two custom entities, entity_one and entity_two. entity_one has a entity reference field that allows you to select unlimited instances of entity_twos. The edit form for entity_one seems to work fine. The field exists and properly auto populates with entity_twos. However as soon as I submit and create an entity_one the list page for entity_ones gives me the error.
Error: Call to a member function getValue() on string in
Drupal\Core\Entity\ContentEntityBase->__sleep() (line 524 of
core/lib/Drupal/Core/Entity/ContentEntityBase.php).
If I remove that particular field and just have textfields I do not encounter this behavior. It only occurs when I have the entity reference field.
My first instinct was maybe in my EntityOneListBuilder.php it uses a field in the table that isn't properly formatted but the only fields used are ID and title.
Here is a portion of my EntityOneListBuilder
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$entity_type,
$container->get('entity_type.manager')->getStorage($entity_type->id()),
$container->get('url_generator')
);
}
public function render() {
$build['description'] = [
'#markup' => $this->t('Description Text'),
];
$build['table'] = parent::render();
return $build;
}
public function buildHeader() {
$header['id'] = $this->t('ID');
$header['title'] = $this->t('Title');
return $header + parent::buildHeader();
}
public function buildRow(EntityInterface $entity) {
$row['id'] = $entity->id();
$row['title'] = $entity->toLink()->toString();
return $row + parent::buildRow($entity);
}
And here is how I'm building the entity reference field for entity_one
$fields['entity_twos'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Form Fields'))
->setDescription(t('The fields to add to this form.'))
->setRevisionable(TRUE)
->setSetting('target_type', 'entity_two')
->setTargetEntityTypeId('entity_two')
->setSetting('handler','default')
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'entity_two',
'weight' => 0,
])
->setDisplayOptions('form', [
'type' => 'entity_reference_autocomplete',
'weight' => 5,
'settings' => [
'autocomplete_type' => 'tags',
'size' => '60',
'match_operator' => 'CONTAINS',
'placeholder' => '',
],
])
->setDisplayConfigurable('form', true)
->setDisplayConfigurable('view', true)
->setRequired(TRUE)
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
Why would that particular field break my collection page?
update: I realize it's possible that the code in entity_two could be what's breaking it. Here's some of the code here for reference
public static function baseFieldDefinitions(
EntityTypeInterface $entity_type
) {
$fields['id'] = BaseFieldDefinition::create('integer')
->setLabel(t('ID'))
->setReadOnly(true);
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setReadOnly(true);
$fields['title'] = BaseFieldDefinition::create('string')
->setLabel(t('Title'))
->setSettings([
'max_length' => 255,
'text_processing' => 0,
])
->setDefaultValue(null)
->setDisplayOptions('view', [
'label' => 'above',
'type' => 'string',
'weight' => -6,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -6,
])
->setDisplayConfigurable('form', true)
->setDisplayConfigurable('view', true);
$fields['field_type'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Field Type'))
->setDisplayOptions('view', [
'label' => 'visible',
'type' => 'list_default',
])
->setSettings([
'allowed_values' => [
'checkbox' => 'Checkbox',
'text_field' => 'Text Field',
],
])
->setDisplayOptions('form', [
'type' => 'options_select',
]);
$fields['allowed_values'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Allowed Values'))
->setDisplayOptions('view', [
'label' => 'visible',
'type' => 'basic_string',
'weight' => 6,
])
->setDisplayOptions('form', [
'type' => 'string_textarea',
'rows' => 6,
'weight' => 6,
'settings' => ['rows' => 4],
])
->setDisplayConfigurable('form', true)
->setDisplayConfigurable('view', true);
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language code'))
->setDescription(
t('The language code of ContentEntityExample entity.')
);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time that the entity was created.'));
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time that the entity was last edited.'));
return $fields;
}
}
Update 2: I can confirm that the error happens when it tries to use getValue() on the entity referenced's id. In ContentEntityBase.php it fails here:
public function __sleep() {
// Get the values of instantiated field objects, only serialize the values.
foreach ($this->fields as $name => $fields) {
foreach ($fields as $langcode => $field) {
$this->values[$name][$langcode] = $field->getValue();
}
}
When the value of $field is just a plain string containing the id of the entity referenced.