2

I've created a custom content entity with a string ID field named 'lot_number':

*   entity_keys = {
*     "id" = "lot_number",

This is its field definition:

$fields['lot_number'] = BaseFieldDefinition::create('string')
  ->setLabel(t('Lot Number'))
  ->setDescription(t('Unique alphanumeric lot number for a batch of inventory.'))
  ->setRequired(TRUE)
  ->setSetting('max_length', 20)
  ->setDisplayOptions('view', array(
    'label' => 'inline',
    'type' => 'string',
    'weight' => 10,
  ))
  ->setDisplayOptions('form', array(
    'type' => 'string_textfield',      
    'weight' => 10,
    'settings' => array(
      'size' => '10',
      ),
  ))
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE)
  ->addConstraint('UniqueField', []);

My problem is that this lot_number field does not show up on the content entity form. I tried adding it to the form programmatically in the buildForm() method of my form controller (that extends ContentEntityForm.) The following code gets it to show up on the form:

$form['lot_number'] = [
  '#type' => 'machine_name',
  '#title' => $this->t('Lot Number'),
  '#weight' => 10,
  '#size' => 20,
  '#maxlength' => 20,
  '#required' => TRUE,
  '#default_value' => $lot_master->getLotNumber(),
  '#machine_name' => [
    'exists' => '\Drupal\galt_inv\Entity\LotMaster::load',
  ],
  '#disabled' => !$lot_master->isNew(),
];

However, when I attempt to submit the form, I get an error message:

Error: Cannot unset string offsets in Drupal\Core\Field\WidgetBase->extractFormValues() (line 354 of core/lib/Drupal/Core/Field/WidgetBase.php).

I tried changing $form['lot_number'] to $form['lot_number']['widget'][0] in an attempt to make it match the rest of the form elements, but that didn't work at all.

Is there some simple way to get a content entity ID onto the content entity edit form? Any advice would be greatly appreciated.

1 Answer 1

3

You have both a widget configured and a custom form element, that results in Drupal being confused about the structure.

If you have a form element defined by yourself, don't define form display options and you should be OK.

The reason the widget show up like with other fields is likely actually a regression with the security fix in 8.3.1 that denies edit access to the entity. When we did that, we didn't anticipate a use case like this. You could override the default fieldAccess() method on the EntityAccessControlHandler to grant edit access to the id field, at least when it is new.

Or you do not make the lot number the actual entity ID but have a technical auto-increment ID, then you don't have to worry about this stuff.

3
  • Thank you! I appreciate all the detailed information. I never would have thought about the EntityAccessControlHandler. I'm giving that a shot, but I think you may be right about just using the standard auto-increment ID instead of lot number. Using the lot number makes my migrations easier, and it makes a lot of the "business logic" simpler, but I have the feeling I'm going to cause myself a lot of aggravation in the long-run if I don't just switch over now.
    – user72086
    Apr 29, 2017 at 19:48
  • Just omitting form display options worked for me, too. However, I'm still wondering where in Drupal's core is the logic that hides the ID field on EntityForms.
    – Hendrik
    Apr 7, 2018 at 12:11
  • Just found one issue: the UniqueField constraint works, but leads to an ugly error message when violated (EntityStorageException) – I'm not sure how to go about validation in this case. Any ideas?
    – Hendrik
    Apr 7, 2018 at 12:17

Your Answer

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