0

I'm still pretty new to D8 so I'm getting to grips with the new way it deals with fields and the OOP way of doing it etc.

I've got a hook in my module which I'm trying to add a submit handler to different types of form submission (user registration, comment forms, webforms etc) and I'm trying to write something which will go through each of the admin added fields (eg, all fields that start with field_ ) and deal with each field type so that I can do something additional with it at the end

In pseudo terms

foreach ($fields as $field_name => $field) {
    if (substr($field_name, 0, 6) === "field_") {
      switch ( //field type ) {
        case 'boolean':
          // if it's a boolean, do this
          break;
  
        case 'entity_reference':
          // if it's an entity reference, do this
          break;

        default:
          // for everything else, do this

          break;
      }
    }
  }

But where my switch statement is, I'm basically having to check against the field definition to determine what type of field I'm checking against, because if I just check against the submit handler answers, it only gives me the response.

Currently I'm getting the definitions by doing this

$definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('entity_type', 'bundle');

Is that the best method to do it? When I tried to run dpm() on this for a custom comment form type, it just seems to kill my site, not like a requirement error, but it just seems to have a memory leak when I try to do it or something.

2
  • The requirement is not so clear, but have you considered using the Entity API hooks? Commented Jan 12, 2021 at 10:07
  • I'm not as familiar with it, but I would assume that would natively give me the field definitions as it's being called from the entity type itself? Does something like hook_ENTITY_TYPE_insert respond to all instances of that type being created? eg, if I did hook_comment_insert, does that respond to all types of comment forms being submitted, or would I have to do one per bundle too? Commented Jan 12, 2021 at 10:36

1 Answer 1

0

Think this is an OOP question... so the correct answer is to switch by the type of the instance. In PHP you do this with "instanceof", like here in MappingTest.php:

protected function filterNumericFields(&$fields) {
    foreach ($this->view->field as $id => $field) {
      if (!($field instanceof NumericField)) {
        unset($fields[$id]);
      }
    }
  }

Note: dpm is bad with nested objects... you should set up a debugger like xdebug.

Another Note: Each content entity has a getFieldDefinitions method:

   /**
   * {@inheritdoc}
   */
  public function getFieldDefinitions() {
    if (!isset($this->fieldDefinitions)) {
      $this->fieldDefinitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($this->entityTypeId, $this->bundle());
    }
    return $this->fieldDefinitions;
  }
3
  • The mean reason I was trying to deal with it based on the field type is that for things like an entity reference, the field structure is referenced with target_id to the node, and as part of my code I wanted to retrieve the referenced entity's title, so only checking that the answer is a number wouldn't work in all instances, because sometimes I really might be checking a numeric value Commented Jan 12, 2021 at 10:34
  • Take a look at this entity cheat sheet: metaltoad.com/blog/drupal-8-entity-api-cheat-sheet. I.e. when you want the title of a referenced entity, you can use magic getters like $node->field_foo->entity->name ... Commented Jan 12, 2021 at 10:37
  • Thanks for that, that'll be useful to keep in general Commented Jan 12, 2021 at 10:47

Your Answer

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

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