I want to create a two-way relationship between a field in a custom entity (package_date) and the field in a content type (package).
I have been able to add a relationship from a view for package_date, but it only allows me to add the linked field to the view, not any other package_date field. When the view is saved, I get this error.
No entity type for field field_package_id on view package_dates in DrupalviewsPluginviewsHandlerBase->getEntityType() (line 697 of coremodulesviewssrcPluginviewsHandlerBase.php)
The package_date entity definition is the following.
namespace Drupalmy_moduleEntity; use DrupalCoreEntityEntityStorageInterface; use DrupalCoreFieldBaseFieldDefinition; use DrupalCoreEntityContentEntityBase; use DrupalCoreEntityEntityTypeInterface; use DrupalCoreEntityEntityChangedTrait; /** * Defines the PackageDate entity. * * @ingroup package_date * * @ContentEntityType( * id = "package_date", * label = @Translation("Package Date"), * handlers = { * "view_builder" = "DrupalCoreEntityEntityViewBuilder", * "views_data" = "DrupalviewsEntityViewsData", * }, * base_table = "package_date", * entity_keys = { * "id" = "id", * "uuid" = "uuid", * }, * admin_permission = "administer package_date entity", * fieldable = true, * ) */ class PackageDate extends ContentEntityBase { use EntityChangedTrait; /** * {@inheritdoc} * * Define the field properties here. * */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { // Standard field, used as unique if primary index. $fields['id'] = BaseFieldDefinition::create('integer') ->setLabel(t('ID')) ->setDescription(t('The ID of the Term entity.')) ->setReadOnly(TRUE); // Standard field, unique outside of the scope of the current project. $fields['uuid'] = BaseFieldDefinition::create('uuid') ->setLabel(t('UUID')) ->setDescription(t('The UUID of the Contact entity.')) ->setReadOnly(TRUE); $fields['package_id'] = BaseFieldDefinition::create('integer') ->setLabel(t('Package ID')) ->setDisplayOptions('view', array( 'label' => 'above', 'type' => 'integer', 'weight' => 0, )) ->setDisplayConfigurable('view', TRUE); $fields['start_datetime'] = BaseFieldDefinition::create('datetime') ->setLabel('Package Start Time') ->setDisplayOptions('view', array( 'label' => 'above', 'type' => 'datetime', 'weight' => 1, )) ->setSetting('datetime_type', 'datetime') ->setSetting('timezone_override', ''); $fields['end_datetime'] = BaseFieldDefinition::create('datetime') ->setLabel('Package End Time') ->setDisplayOptions('view', array( 'label' => 'above', 'type' => 'datetime', 'weight' => 2, )) ->setSetting('datetime_type', 'datetime') ->setSetting('timezone_override', ''); $fields['price'] = BaseFieldDefinition::create('decimal') ->setLabel(t('Package Price')) ->setSettings(array( 'precision' => 10, 'scale' => 4, 'decimal_separator' => '.', )) ->setDisplayOptions('view', array( 'label' => 'above', 'type' => 'decimal', 'weight' => 0, )) ->setDisplayConfigurable('view', TRUE); $fields['capacity'] = BaseFieldDefinition::create('integer') ->setLabel(t('Capacity')) ->setDisplayOptions('view', array( 'label' => 'above', 'type' => 'integer', 'weight' => 0, )) ->setDisplayConfigurable('view', TRUE); $fields['availability'] = BaseFieldDefinition::create('integer') ->setLabel(t('Availability')) ->setDisplayOptions('view', array( 'label' => 'above', 'type' => 'integer', 'weight' => 0, )) ->setDisplayConfigurable('view', TRUE); $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; } }
The hook_view_data()
implementation uses the following code.
function my_module_views_data() { $data['package_date']['table']['group'] = t('Package Dates'); $data['package_date']['table']['join'] = array( // Index this array by the table name to which this table refers. // 'left_field' is the primary key in the referenced table. // 'field' is the foreign key in this table. 'node__field_package_id' => array( 'left_field' => 'field_package_id_value', 'field' => 'package_id', ), ); $data['package_date']['package_id'] = array( 'title' => t('Package ID'), 'relationship' => array( 'base' => 'node__field_package_id', // The name of the table to join with. 'base field' => 'field_package_id_value', // The name of the field on the joined table. // 'field' => 'package_id' -- see hook_views_data_alter(); not needed here. 'handler' => 'views_handler_relationship', 'label' => t('Relationship between Package and Package Dates'), 'title' => t('Package to Package Dates Relationship'), 'id' => 'standard', ), ); return $data; }
The exported view is the following one.
langcode: en status: true dependencies: config: - system.menu.admin module: - datetime - pve - user id: _package_dates label: 'Package Dates' module: views description: 'Display current cache of Package Dates' tag: '' base_table: _package_date base_field: id core: 8.x display: default: display_plugin: default id: default display_title: Master position: 0 display_options: access: type: perm options: perm: 'access site reports' cache: type: tag options: { } query: type: views_query options: disable_sql_rewrite: false distinct: false replica: false query_comment: '' query_tags: { } exposed_form: type: basic options: submit_button: Apply reset_button: false reset_button_label: Reset exposed_sorts_label: 'Sort by' expose_sort_order: true sort_asc_label: Asc sort_desc_label: Desc pager: type: full options: items_per_page: 50 offset: 0 id: 0 total_pages: null tags: previous: ‹‹ next: ›› first: '« First' last: 'Last »' expose: items_per_page: false items_per_page_label: 'Items per page' items_per_page_options: '5, 10, 25, 50' items_per_page_options_all: false items_per_page_options_all_label: '- All -' offset: false offset_label: Offset quantity: 9 style: type: table row: type: fields fields: _package_id: table: _package_date field: _package_id id: _package_id entity_type: null entity_field: _package_id plugin_id: field relationship: none group_type: group admin_label: '' label: 'Package ID' exclude: false alter: alter_text: false text: '' make_link: false path: '' absolute: false external: false replace_spaces: false path_case: none trim_whitespace: false alt: '' rel: '' link_class: '' prefix: '' suffix: '' target: '' nl2br: false max_length: 0 word_boundary: true ellipsis: true more_link: false more_link_text: '' more_link_path: '' strip_tags: false trim: false preserve_tags: '' html: false element_type: '' element_class: '' element_label_type: '' element_label_class: '' element_label_colon: true element_wrapper_type: '' element_wrapper_class: '' element_default_classes: true empty: '' hide_empty: false empty_zero: false hide_alter_empty: true click_sort_column: value type: number_integer settings: { } group_column: value group_columns: { } group_rows: true delta_limit: 0 delta_offset: 0 delta_reversed: false delta_first_last: false multi_type: separator separator: ', ' field_api_classes: false start_datetime: id: start_datetime table: _package_date field: start_datetime relationship: none group_type: group admin_label: '' label: 'Package Start Time' exclude: false alter: alter_text: false text: '' make_link: false path: '' absolute: false external: false replace_spaces: false path_case: none trim_whitespace: false alt: '' rel: '' link_class: '' prefix: '' suffix: '' target: '' nl2br: false max_length: 0 word_boundary: true ellipsis: true more_link: false more_link_text: '' more_link_path: '' strip_tags: false trim: false preserve_tags: '' html: false element_type: '' element_class: '' element_label_type: '' element_label_class: '' element_label_colon: true element_wrapper_type: '' element_wrapper_class: '' element_default_classes: true empty: '' hide_empty: false empty_zero: false hide_alter_empty: true click_sort_column: value type: datetime_default settings: timezone_override: '' format_type: medium group_column: value group_columns: { } group_rows: true delta_limit: 0 delta_offset: 0 delta_reversed: false delta_first_last: false multi_type: separator separator: ', ' field_api_classes: false entity_type: _package_date entity_field: start_datetime plugin_id: field end_datetime: id: end_datetime table: _package_date field: end_datetime relationship: none group_type: group admin_label: '' label: 'Package End Time' exclude: false alter: alter_text: false text: '' make_link: false path: '' absolute: false external: false replace_spaces: false path_case: none trim_whitespace: false alt: '' rel: '' link_class: '' prefix: '' suffix: '' target: '' nl2br: false max_length: 0 word_boundary: true ellipsis: true more_link: false more_link_text: '' more_link_path: '' strip_tags: false trim: false preserve_tags: '' html: false element_type: '' element_class: '' element_label_type: '' element_label_class: '' element_label_colon: true element_wrapper_type: '' element_wrapper_class: '' element_default_classes: true empty: '' hide_empty: false empty_zero: false hide_alter_empty: true click_sort_column: value type: datetime_default settings: timezone_override: '' format_type: medium group_column: value group_columns: { } group_rows: true delta_limit: 0 delta_offset: 0 delta_reversed: false delta_first_last: false multi_type: separator separator: ', ' field_api_classes: false entity_type: _package_date entity_field: end_datetime plugin_id: field availability: id: availability table: _package_date field: availability relationship: none group_type: group admin_label: '' label: Availability exclude: false alter: alter_text: false text: '' make_link: false path: '' absolute: false external: false replace_spaces: false path_case: none trim_whitespace: false alt: '' rel: '' link_class: '' prefix: '' suffix: '' target: '' nl2br: false max_length: 0 word_boundary: true ellipsis: true more_link: false more_link_text: '' more_link_path: '' strip_tags: false trim: false preserve_tags: '' html: false element_type: '' element_class: '' element_label_type: '' element_label_class: '' element_label_colon: true element_wrapper_type: '' element_wrapper_class: '' element_default_classes: true empty: '' hide_empty: false empty_zero: false hide_alter_empty: true click_sort_column: value type: number_integer settings: thousand_separator: '' prefix_suffix: true group_column: value group_columns: { } group_rows: true delta_limit: 0 delta_offset: 0 delta_reversed: false delta_first_last: false multi_type: separator separator: ', ' field_api_classes: false entity_type: _package_date entity_field: availability plugin_id: field capacity: id: capacity table: _package_date field: capacity relationship: none group_type: group admin_label: '' label: Capacity exclude: false alter: alter_text: false text: '' make_link: false path: '' absolute: false external: false replace_spaces: false path_case: none trim_whitespace: false alt: '' rel: '' link_class: '' prefix: '' suffix: '' target: '' nl2br: false max_length: 0 word_boundary: true ellipsis: true more_link: false more_link_text: '' more_link_path: '' strip_tags: false trim: false preserve_tags: '' html: false element_type: '' element_class: '' element_label_type: '' element_label_class: '' element_label_colon: true element_wrapper_type: '' element_wrapper_class: '' element_default_classes: true empty: '' hide_empty: false empty_zero: false hide_alter_empty: true click_sort_column: value type: number_integer settings: thousand_separator: '' prefix_suffix: true group_column: value group_columns: { } group_rows: true delta_limit: 0 delta_offset: 0 delta_reversed: false delta_first_last: false multi_type: separator separator: ', ' field_api_classes: false entity_type: _package_date entity_field: capacity plugin_id: field created: id: created table: _package_date field: created relationship: none group_type: group admin_label: '' label: Created exclude: false alter: alter_text: false text: '' make_link: false path: '' absolute: false external: false replace_spaces: false path_case: none trim_whitespace: false alt: '' rel: '' link_class: '' prefix: '' suffix: '' target: '' nl2br: false max_length: 0 word_boundary: true ellipsis: true more_link: false more_link_text: '' more_link_path: '' strip_tags: false trim: false preserve_tags: '' html: false element_type: '' element_class: '' element_label_type: '' element_label_class: '' element_label_colon: true element_wrapper_type: '' element_wrapper_class: '' element_default_classes: true empty: '' hide_empty: false empty_zero: false hide_alter_empty: true click_sort_column: value type: timestamp settings: date_format: medium custom_date_format: '' timezone: '' group_column: value group_columns: { } group_rows: true delta_limit: 0 delta_offset: 0 delta_reversed: false delta_first_last: false multi_type: separator separator: ', ' field_api_classes: false entity_type: _package_date entity_field: created plugin_id: field changed: id: changed table: _package_date field: changed relationship: none group_type: group admin_label: '' label: Changed exclude: false alter: alter_text: false text: '' make_link: false path: '' absolute: false external: false replace_spaces: false path_case: none trim_whitespace: false alt: '' rel: '' link_class: '' prefix: '' suffix: '' target: '' nl2br: false max_length: 0 word_boundary: true ellipsis: true more_link: false more_link_text: '' more_link_path: '' strip_tags: false trim: false preserve_tags: '' html: false element_type: '' element_class: '' element_label_type: '' element_label_class: '' element_label_colon: true element_wrapper_type: '' element_wrapper_class: '' element_default_classes: true empty: '' hide_empty: false empty_zero: false hide_alter_empty: true click_sort_column: value type: timestamp settings: date_format: medium custom_date_format: '' timezone: '' group_column: value group_columns: { } group_rows: true delta_limit: 0 delta_offset: 0 delta_reversed: false delta_first_last: false multi_type: separator separator: ', ' field_api_classes: false entity_type: _package_date entity_field: changed plugin_id: field filters: { } sorts: { } title: 'Package Dates' header: { } footer: { } empty: area_text_custom: id: area_text_custom table: views field: area_text_custom relationship: none group_type: group admin_label: '' empty: true tokenize: false content: '<p>There is currently no data to display.</p>' plugin_id: text_custom relationships: _package_id: id: _package_id table: _package_date field: _package_id relationship: none group_type: group admin_label: 'Relationship between Package and Package Dates' required: false entity_type: _package_date entity_field: _package_id plugin_id: standard arguments: { } display_extenders: { } cache_metadata: max-age: 0 contexts: - 'languages:language_content' - 'languages:language_interface' - url.query_args - user.permissions tags: { } _package_dates_report: display_plugin: page id: _package_dates_report display_title: 'Package Dates' position: 1 display_options: display_extenders: { } path: admin/-package-dates menu: type: normal title: 'Package Dates' description: '' expanded: false parent: system.admin_reports weight: 0 context: '0' menu_name: admin display_description: '' cache_metadata: max-age: 0 contexts: - 'languages:language_content' - 'languages:language_interface' - url.query_args - user.permissions tags: { }
It looks like the relationships property is the wrong way around, but I’m not sure.
I’d also like to be able to create a view for the package content type, and link this to the package_date entity. When trying to do so, I don’t have a relationship I can add.
I expect I’m missing one or more things to get this working, but I’m not sure what. At the very least, I think I need the inverse of the defined relationship, but I’m sure that’s not the only issue.
Sponsored by SupremePR