Score:0

Creating an instance of custom entity with entity reference field breaks entity collection page

cn flag

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.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.