0

I thought that omitting code and being more graphic was going to improve the question, but that only made it score negative hehehe. So I'm going to put in some code to make it look clearer. Here is the second version of my question.


I am developing a customized module, to implement a series of entities, with the following model: Data Model

In blue, the Drupal core entity (User) and in white, the ones I have defined (Member, Calendar and Attendance). Except for User, all other fields are literal. I have only omitted UUID in my entities.

Here is the code that defines the Member entity: Member entity: Annotation

 * @ContentEntityType(
 *   id = "ita_member",
 *   label = @Translation("Miembro"),
 *   label_collection = @Translation("Miembros"),
 *   label_singular = @Translation("miembro"),
 *   label_plural = @Translation("miembros"),
 *   label_count = @PluralTranslation(
 *     singular = "@count miembro",
 *     plural = "@count miembros",
 *   ),
 *   base_table = "ita_members",
 *   handlers = {
 *     "route_provider" = {
 *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
 *     },
 *     "form" = {
 *       "default" = "Drupal\ita\Form\RegistrationForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *     },
 *     "list_builder" = "Drupal\ita\Entity\Handler\MemberListBuilder",
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "views_data" = "Drupal\views\EntityViewsData",
 *   },
 *   entity_keys = {
 *      "id" = "id",
 *      "uuid" = "uuid",
 *   },
 *   links = {
 *     "add-form" = "/ita/add",
 *     "canonical" = "/ita/{ita_member}",
 *     "collection" = "/admin/content/itas",
 *     "delete-form" = "/ita/{ita_member}/delete",
 *     "edit-form" = "/ita/{ita_member}/edit",
 *   },
 *   admin_permission = "administer members",
 *   fieldable = TRUE,
 *   field_ui_base_route = "entity.ita_member.settings",
 *   common_reference_target = TRUE,
 * )

Member entity: baseFieldDefinitions

  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
      $fields = parent::baseFieldDefinitions($entity_type);

      // User
      $fields['user'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Usuario'))
      ->setDescription(t('Identificador del usuario del sistema asignado a este miembro.'))
      ->setSetting('target_type', 'user')
      ->setRequired(TRUE)
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'string',
        'weight' => 2,
      ])
      ->setDisplayOptions('form', [
        'type' => 'entity_reference_autocomplete',
        'weight' => 2,
        'settings' => [
          'match_operator' => 'CONTAINS',
          'size' => '25',
          'placeholder' => 'Teclee el nombre del usuario',
        ],
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->addConstraint('UniqueField');

      return $fields;
  }

Calendar entity: Annotation

 * @ContentEntityType(
 *   id = "ita_calendar",
 *   label = @Translation("Calendario de asistencias"),
 *   label_collection = @Translation("Calendarios"),
 *   label_singular = @Translation("Calendario"),
 *   label_plural = @Translation("Calendario de asistencias"),
 *   label_count = @PluralTranslation(
 *     singular = "@count Calendario",
 *     plural = "@count Calendarios",
 *   ),
 *   base_table = "ita_calendar",
 *   handlers = {
 *     "route_provider" = {
 *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
 *     },
 *     "form" = {
 *       "default" = "Drupal\ita\Form\CalendarForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *     },
 *     "list_builder" = "Drupal\ita\Entity\Handler\CalendarListBuilder",
 *     "views_data" = "Drupal\ita\Entity\Handler\CalendarViewsData",
 *   },
 *   fieldable = TRUE,
 *   entity_keys = {
 *      "id" = "id",
 *      "uuid" = "uuid",
 *   },
 *   links = {
 *     "add-form" = "/calendar/add",
 *     "canonical" = "/calendar/{ita_calendar}",
 *     "collection" = "/admin/content/calendar",
 *     "delete-form" = "/calendar/{ita_calendar}/delete",
 *     "edit-form" = "/calendar/{ita_calendar}/edit",
 *   },
 *   admin_permission = "administer calendar",
 *   field_ui_base_route = "entity.ita_calendar.settings",
 *   common_reference_target = TRUE,
 * )

Calendar entity: baseFieldDefinitions

public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
      $fields = parent::baseFieldDefinitions($entity_type);

      // Date Attendance
      $fields['date'] = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Fecha de asistencia'))
      ->setDescription(t('Fecha en la que se va a pasar lista de asistencia.'))
      ->setRevisionable(FALSE)
      ->setRequired(TRUE)

      ->setSettings([
        'datetime_type' => 'date',
      ])

      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'datetime_default',
        'settings' => [
          'format_type' => 'd/m/Y',
        ],
        'weight' => 0,
      ])
      ->setDisplayOptions('form', [
        'type' => 'datetime_default',
        'weight' => 0,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->addConstraint('UniqueField');

      // Type Attendance
      $fields['type'] = BaseFieldDefinition::create('list_string')
      ->setLabel(t('Tipo de asistencia'))
      ->setDescription(t('Tipo de asistencia (Obligatoria, Voluntaria o Anulada) para esta fecha.'))
      ->setRequired(TRUE)
      ->setSettings([
        'max_length', '3',
        'allowed_values' => [
          'anu' => 'Anulada',
          'obl' => 'Obligatoria',
          'vol' => 'Voluntaria',
          ],
        ])
      ->setDefaultValue('obl')
      ->setDisplayOptions('view', [
          'label' => 'above',
          'type' => 'string',
          'weight' => 1,
        ])
      ->setDisplayOptions('form', [
          'type' => 'options_select',
          'weight' => 1,
        ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

      return $fields;
  }

Attendance entity: Annotation

 * @ContentEntityType(
 *   id = "ita_attendance",
 *   label = @Translation("Registro de asistencia"),
 *   label_collection = @Translation("Asistencias"),
 *   label_singular = @Translation("Asistencia"),
 *   label_plural = @Translation("Asistencias"),
 *   label_count = @PluralTranslation(
 *     singular = "@count Asistencia",
 *     plural = "@count Asistencias",
 *   ),
 *   base_table = "ita_attendances",
 *   handlers = {
 *     "route_provider" = {
 *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
 *     },
 *     "form" = {
 *       "default" = "Drupal\Core\Entity\ContentEntityForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *     },
 *     "views_data" = "Drupal\views\EntityViewsData",
 *   },
 *   fieldable = TRUE,
 *   entity_keys = {
 *      "id" = "id",
 *      "uuid" = "uuid",
 *   },
 *   links = {
 *     "add-form" = "/attendance/add",
 *     "canonical" = "/attendance/{ita_attendance}",
 *     "collection" = "/admin/content/attendance",
 *     "delete-form" = "/attendance/{ita_attendance}/delete",
 *     "edit-form" = "/attendance/{ita_attendance}/edit",
 *   },
 *   admin_permission = "administer attendance",
 *   field_ui_base_route = "entity.ita_attendance.settings",
 * )

Attendance entity: baseFieldDefinitions

public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
      $fields = parent::baseFieldDefinitions($entity_type);

      // Date Attendance
      $fields['date'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Fecha'))
      ->setDescription(t('Fecha en la que se desea registrar la asistencia.'))
      ->setSetting('target_type', 'ita_calendar')
      ->setSettings([
        'handler', 'views',
        'handler_settings', [
          'view' => [
            'view_name' => 'Listado de fechas',
            'display_name' => 'default',
          ],
        ],
        'auto_create' => FALSE,
      ])
      ->setRequired(TRUE)
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'string',
        'weight' => 1,
      ])
      ->setDisplayOptions('form', [
        'type' => 'options_select',
        'weight' => 1,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

      // Member
      $fields['user'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Usuario'))
      ->setDescription(t('Miembro al que se le va a pasar lista.'))
      ->setSetting('target_type', 'ita_member')
      ->setRequired(TRUE)
      ->setDisplayOptions('view', [
        'label' => 'visible',
        'type' => 'entity_reference_label',
        'settings' => [
          'link' => TRUE,
        ],
        'weight' => 1,
      ])
      ->setDisplayOptions('form', [
        'type' => 'options_select',
        'weight' => 1,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);


      return $fields;
  }

The foreign keys are entity reference type fields. The user field in the Member entity works perfectly. The ones that don't work are the two from the Attendance entity. In this case, I use a "select list" widget to verify it, it is observed that there is information, but nothing else is seen. The content appears, but empty (blank content). This is the output I have in the form to add new attendances.

Member widget content

And as you can see from above, here I only use the standard handlers.

handlers = {
 *     "route_provider" = {
 *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
 *     },
 *     "form" = {
 *       "default" = "Drupal\Core\Entity\ContentEntityForm",
 *       "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
 *     },
 *     "views_data" = "Drupal\views\EntityViewsData",

I am doing all this programmatically, so I have created the member field, for example, by hand and the result is the same. However, if the field I create by hand, I attach a view of type "Entity Reference" does work. I think that I have to customize something so that the autocomplete or the select list of a custom entity returns the data correctly. I believe that the problem is in that I have not defined the habitual fields of an entity type node, as it is the title, for example. I hope that it has been clear the problem and can exist, sure that yes, a solution. I have my suspicions that the solution is to implement the ViewsData or ViewsListBuilder handlers, but honestly, I have no idea.

1
  • 1
    You haven't shared any of the code that powers this to know what's wrong. All I can guess at a glance is you haven't defined an entity label. – Kevin Jan 2 at 13:58
1

As Kevin mentioned in the comments, your entity types don't have a label set for entity_keys, and presumably you haven't overridden EntityBase::label in any of them. This means that when the system requests a label for an entity, it gets NULL, and you see a blank string.

If your entity type has a string field you can use for the title, set it in the annotation:

*  entity_keys = {
*    "id" = "id",
*    "uuid" = "uuid",
*    "label" = "title",
*  },

If not, override the label method in the entity class:

public function label() {
  return $this->user->entity->name;
}
1
  • Thanks to both of you. Your proposal has worked perfectly. I knew something strange was happening and it had to be something like that. I didn't imagine it would be so simple. I was thinking of implementing a ViewsData, Plugin,... but there is no need, with this, it works for me. Thank you very much. – jasn Jan 2 at 20:42

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.