3

Edit: My question is similar to How to create multi-value, multi-bundle entity reference fields in code?, except the field doesn't need to reference multiple bundles.

We have an existing view of custom entities. The view needs to now be filtered based on some related fields that are not part of the entity (or any entity). Kind of like adding a Taxonomy Reference field to a Content Type. What is the best way to add those fields to the entity?

I see that many modules use attachLoad to attach fields to an entity, but when I try my implementation those fields don't show up in my list of Fields or Filters in Views.

This is a screenshot of the checkboxes field:

enter image description here

This is my controller:

class ContactsController extends EntityAPIController {

  public function attachLoad(&$queried_entities, $revision_id = FALSE)
  {
    foreach ($queried_entities as $key => $entity)
    {
      $queried_entities[$key]->foo = "bar";
    }
    parent::attachLoad($queried_entities, $revision_id);
  }

}

And this is my hook_entity_info:

function contacts_entity_info() {
  $return = array(
    'contacts' => array(
      'label' => t('Contact'),
      'entity class' => 'Contacts',
      'controller class' => 'ContactsController',
      'views controller class' => 'ContactsViewsController',
      'base table' => 'contacts',
      'fieldable' => TRUE,
      'entity keys' => array(
        'id' => 'ckid',
        'bundle' => array(),
      ),
      'bundle keys' => array(),
      'bundles' => array(),
      'load hook' => 'contacts_load',
      'view modes' => array(
        'full' => array(
          'label' => t('Default'),
          'custom settings' => FALSE,
        ),
      ),
      'label callback' => 'entity_class_label',
      'uri callback' => 'entity_class_uri',
      'module' => 'contacts',
      'access callback' => 'contacts_access',
    ),
  );

  return $return;
}

This is a suggested implementation of EntityDefaultViewsController:

/**
* EntityTest Views Controller class.
*/
class ContactsViewsController extends EntityDefaultViewsController {

  /**
   * Add extra fields to views_data().
   */
  public function views_data() {
    $data = parent::views_data();

    // Add your custom data here
    $data['contacts_topics']['table'] = array(
      'group' => t('Contacts Topics'),
      'base' => array(
        'field' => 'ckid',
        'title' => t('Contacts Topics'),
      ),
      'join' => array(
        'contacts' => array(
          'left_field' => 'ckid',
          'field' => 'ckid',
        ),
      ),
    );

    $data['contacts_topics'] = array(
      'ckid' => array(
        'title' => 'Contact Entity ID',
        'field' => array(
          'handler' => 'views_handler_field_numeric',
          'click sortable' => TRUE,
        ),
        'sort' => array(
          'handler' => 'views_handler_sort',
        ),
        'filter' => array(
          'handler' => 'views_handler_filter_numeric',
        ),
        'relationship' => array(
          'base' => 'contacts',
          'base field' => 'ckid',
          'handler' => 'views_handler_relationship',
          'label' => t('Contact entity relationship'),
          'title' => t('Conact entity relationship'),
        ),
      ),
    );

    return $data;
  }
}

Unfortunately I don't see anything in the Views SQL that shows that any of these attempts to add the fields or join the topics table to the contacts table are working.

5
  • how are these un-related fields 'related' to your entity. How do these entities know to show X other fields in addition to their own??
    – tenken
    Dec 12, 2012 at 18:53
  • There is no entity relationship between them, it's simply an extraneous table I've defined in schema. It's a many-to-many relationship, so each contact can have many topics. The examples I've seen is simply a many-to-one example, and the deadline is ticking :( Dec 12, 2012 at 22:02
  • It's kind of like I want to add a taxonomy field to this entity, so users can select any different kind of topics they are interested in, but I don't want to define a separate field for each topic... Dec 12, 2012 at 22:19
  • I just found the Relation module... I'm thinking this might be what I'm looking for Dec 12, 2012 at 22:42
  • Relation was very quick and easy to get going, but the problem is that the Views integration didn't go far enough to provide the related entity as a Filter... going back to the beginning again. Dec 13, 2012 at 17:59

1 Answer 1

3

How to attach a field to an entity programically solved this problem for me. It's not an exact duplicate, but the answer and the comments pointed me to the right direction.

So this code creates the field and the instance and it attaches it to the entity very nicely:

function contacts_enable()
{
  if (!field_info_field('related_topics'))
  {
    $field = array(
      'field_name' => 'related_topics',
      'type' => 'list_text',
      'cardinality' => -1,
      'settings' => array(
        'allowed_values_function' => '_contacts_get_related_topics',
      ),
    );

    field_create_field($field);

    $instance = array(
      'field_name' => 'related_topics',
      'entity_type' => 'contacts',
      'label' => 'Related Topics',
      'bundle' => 'contacts',
      'default_value' => NULL,
      'settings' => array(
        'user_register_form' => FALSE,
      ),
      'widget' => array(
        'active' => 1,
        'module' => 'options',
        'settings' => array(),
        'type' => 'options_buttons',
        'weight' => -1,
      ),
    );

    field_create_instance($instance);
  }
}
1
  • Nice one Jonathan, thanks. In case somebody is wondering, if you use a structure like the Model project to create entities, a good point to place the above code (properly adapted of course) would be function save of ModelTypeController (which is based on EntityAPIControllerExportable).
    – Wtower
    Feb 11, 2014 at 8:12

Your Answer

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

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