I have several fields that I'd like to attach to a custom entity upon installation. I am trying to follow the suggestions here to attach fields to my custom entity (which, by the way, has no bundles). I know the instructions are for content types, but I am trying to take what's there and apply it to custom entities.

I am attempting to do this through having some field config files in the config/install directory of my module. When I install the module, the fields are created, but they are not attached to the custom entity. When I create and save an instance of my custom entity, and then attempt to see the fields that are attached to my custom entity using a ksm() print, it only shows the base fields defined in my entity. I am trying to add these other fields through config files instead of hard coding them through the base field definitions as these additional fields are meant to be configurable, and according to this the base fields definitions should only be used to define non-configurable fields. The link talks about adding configurable fields through some hooks, but I'd prefer to do it through this configuration solution I am trying, it seems like it should be possible...

So my question is: Is the way that I'm going about doing this possible for a bundle-less entity, and I'm just missing something? Or do I just have to declare all my fields in the base field definitions? Here is the relevant code:



namespace Drupal\questionnaire\Entity;

use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;

 * Defines the QuestionnaireResult entity.
 * @ContentEntityType(
 *   id = "questionnaire_result",
 *   label = @Translation("Questionnaire Result"),
 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\Core\Entity\EntityListBuilder",
 *     "views_data" = "Drupal\views\EnitityViewsData",
 *     "form" = {
 *       "default" = "Drupal\Core\Entity\ContentEntityForm",
 *       "add" = "Drupal\Core\Entity\ContentEntityForm",
 *       "edit" = "Drupal\Core\Entity\ContentEntityForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *     },
 *     "inline_form" = "Drupal\inline_entity_form\Form\EntityInlineForm",
 *     "route_provider" = {
 *       "default" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
 *     },
 *   },
 *   base_table = "questionnaire_result",
 *   admin_permission = "administer site configuration",
 *   entity_keys = {
 *     "id" = "id",
 *     "uuid" = "uuid",
 *   },
 *   links = {
 *     "canonical" = 
 *      "/admin/structure/questionnaire/result/{questionnaire_result}",
 *     "collection" = "/admin/structure/questionnaire/result/overview",
 *   },
 * )
class QuestionnaireResult extends ContentEntityBase 
  implements QuestionnaireResultInterface {

  public function getMessage() {



   * Meant for declaring non-configurable fields only.
  public static function baseFieldDefinitions(EntityTypeInterface 
    $entity_type) {

    // Standard field, used as unique if primary index.
    $fields['id'] = BaseFieldDefinition::create('integer')
      ->setDescription(t('The ID of the Questionnaire Result entity.'))

    // Standard field, unique outside of the scope of the current project.
    $fields['uuid'] = BaseFieldDefinition::create('uuid')
      ->setDescription(t('The UUID of the Questionnaire Result entity.'))

    return $fields;



langcode: en
status: true
    - field.storage.questionnaire_result.field_q_quiz_result_passed
id: questionnaire_result.default.field_q_quiz_result_passed
field_name: field_q_quiz_result_passed
entity_type: questionnaire_result
bundle: default
label: Passed
description: 'Boolean value for whether the user passed the quiz on this attempt or not.'
required: false
translatable: false
    value: 0
default_value_callback: ''
  on_label: 'True'
  off_label: 'False'
field_type: boolean


langcode: en
status: true
    - questionnaire
id: questionnaire_result.field_q_quiz_result_passed
field_name: field_q_quiz_result_passed
entity_type: questionnaire_result
type: boolean
settings: {  }
module: core
locked: false
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false
  • 1
    The default name for the bundle is not default but the same name as the entity, so the prefix for the field config is field.field.questionnaire_result.questionnaire_result. BTW if you want to configure the field first in UI and then export the YAML code, you can make a bundle less entity configurable as well, see drupal.stackexchange.com/questions/283826/…
    – 4k4
    Dec 2 '19 at 13:53
  • @4k4 I see, thank you. Does that mean I need to change the bundle: default in the field config YAML to be the name of the entity as well? Dec 2 '19 at 13:58
  • Yes, the placeholder for the non-existing bundle is always the entity type id.
    – 4k4
    Dec 2 '19 at 14:14

I implemented the suggestion that 4k4 had given, which was to rename my field assignment config from field.field.questionnaire_result.default.field_q_quiz_result_passed.yml to field.field.questionnaire_result.questionnaire_result.field_q_quiz_result_passed.yml. This worked because I was assuming the default bundle's name on a bundle-less entity was 'default', but instead it is the name of the entity itself. I then changed any bundle: default assignment I had to bundle: questionnaire_result.

Once I printed the field definitions after these changes, the field_q_quiz_result_passed was attached to my custom entity.

  • could you show the code for your comment "Once I printed the field definitions"? Thanks
    – esod
    Oct 3 '20 at 19:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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