0

How to output the data entered in Composed Fields to Views?

I have used Composed fields of 3 subfields, it was OK while entering the data. But When I want to display the entered data in Views, I get only blank fields.

After digging dip into it, I tried rewrite the Result, Only in Write result I get Token like [field_field_name-composed], which outputs the serialized PHP code:

a:3:{i:1;s:14:"First Subfield";i:2;s:15:"Second Subfield";i:3;s:14:"Third Subfield";}

where First Subfield, Second Subfield, Third Subfield are the data I entered into 3 subfields of Composed field, and is also defined by s: before it. If it is String type and 14 Characters long, then its written as s:14:

I also see the Token like [field_field_name] but it outputs blank (NULL).

So, I planned to use Views PHP to get the data from Composed Field and use some PHP code, but in Views PHP field, I am unable to use the Token [field_field_name-composed].

I want to make a Views with 3 fields to display each Subfield in its own field, is it possible?

EDIT:

I came to know this is using PHP Serialize function, but when I tried PHP Unserialize in Views PHP, I get blank string.

EDIT2:

The result of Unserialized value of above serialized field is:

print_r(unserialize('a:3:{i:1;s:14:"First Subfield";i:2;s:15:"Second Subfield";i:3;s:14:"Third Subfield";}'));
Array
(
    [1] => First Subfield
    [2] => Second Subfield
    [3] => Third Subfield
)
5
  • In your last sentence, do you mean, 'I want to make a View with 3 columns to display each subfield in it's own column' or did you mean 'I want to make a View with 3 rows to display each subfield in it's own row'?
    – leexonline
    Commented Mar 18, 2014 at 19:29
  • I might not be much familiar with terminology, but for eg: In views If I want to select Title then in fields to add, I select title and so on. I can add three fields in views, if that lets me display all the three values (subfields1..3) separately.
    – user12947
    Commented Mar 18, 2014 at 19:40
  • Please read and re-read what I wrote. You say you want a View with 3 rows but the number of rows in a view is determined by the number of results. I think you mean you want 3 rows for each result but then you go on to say you want 3 columns as well, which makes more sense. Which do you want? 1 row for each result with 3 columns or 3 rows for each result?
    – leexonline
    Commented Mar 18, 2014 at 20:35
  • In the above serialize code there are 3 strings as I mentioned in question. I want to output those 3 different string in 3 different forms. I don't want to display 3 strings together in same field, but make 3 different fields and display each string in each of these.
    – user12947
    Commented Mar 18, 2014 at 20:40
  • @leexonline: I have adjusted the question if that was confusing you. If you still have confusions then please let me know, I'll try to explain as much as possible.
    – user12947
    Commented Mar 18, 2014 at 20:53

2 Answers 2

0
+100

There are several problems with Composed Field module. Some issues with text format handling prevented the values from ever showing up at views! See https://drupal.org/node/1929462 for a fix for that.

Now, once displaying the field in views is fixed, choosing the field components to display is not hard. First of all, you will have to override the field handler for composed fields. It's not harder than this:

 /**
    * Implements hook_field_views_data_views_data_alter().
    */
    function composed_field_field_views_data_views_data_alter(&$data, $field) {
      $field_name = $field['field_name'];
      $data['field_data_' . $field_name][$field_name]['field']['handler'] = 'composed_field_handler_field_composed_field';
    }

Then, in the overriden handler, inherit all you can from views_handler_field_field, which implements everything you need to display a field in views. But let's override three methods:

/**
 * Defines options for composed fields.
 */
function option_definition() {
  $options = parent::option_definition();
  $options['composed_field']['components'] = array('default' => array());
  return $options;
}

This just tells Views we will be setting up some options in the form. It is needed to actually save the values. Mind the parent call, it is needed.

/**
 * Defines checkboxes for composed field components in a fieldset.
 */
function options_form(&$form, &$form_state) {
  parent::options_form($form, $form_state);

  $field_name = $this->field_info['field_name'];

Composed Field lets you set the components for every field instance, meaning the same field might be used in wildly different ways. And since views uses the same handler for any field_instance of the same field, we can't rely on component titles (the composed_field doesn't enforce the titles anyway) nor how many components a field has. We have to figure it out in a more abstract way: just pick the biggest number of components for that field.

  $cardinalities = array();

  foreach ($this->field_info['bundles'] as $entity_type => $bundles) {
    foreach ($bundles as $bundle) {
      $instance = field_info_instance($entity_type, $field_name, $bundle);
      $cardinalities[] = $instance['widget']['settings']['number_of_subfields'];
    }
  }

  // Let's just get the maximum number of subfields.
  $cardinality = max($cardinalities);

Then, just create a form. No surprises here, except tha #tree is TRUE by default (and that's why we have to put option in a keyed array in the previous method).

  $form['composed_field'] = array(
    '#type' => 'fieldset',
    '#title' => t('Composed Field Components'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    'components' => array(
      '#title' => t('Select the field components to display'),
      '#description' => t('If no component is selected, all will be displayed.'),
      '#type' => 'checkboxes',
      '#options' => $this->composed_field_component_options($cardinality),
      '#default_value' => $this->options['composed_field']['components'],
    ),
  );
}

That will be enough to have a UI in views to choose the components (composed_field_component_options() is an implementation detail, but it has to be keyed by the component numeric id, which is not 0-indexed).

Now, to display only the selected components:

/**
 * Filter out disabled components.
 */
function set_items($values, $row_id) {
  $items = parent::set_items($values, $row_id);

  $components = array_filter($this->options['composed_field']['components']);
  // If no component was chosen, show all. This makes for a good default.
  if (!empty($components)) {
    foreach ($items as $delta => $item) {
      foreach ($item['rendered']['#item'] as $component => $value) {
        if (!in_array($component, $components)) {
          unset($items[$delta]['rendered']['#item'][$component]);
        }
      }
    }
  }

  return $items;
}

That last part is easy: retrieve data from the handler options and unset the components that were not selected to be displayed. Of course, display every component if no component was selected (a reasonable default).

1

Write a function in your module/theme that will accept two arguments,

1) the serialized value a:3:i:1;s:3:"First Subfield";i:2;s:4:"Second Subfield";i:3;s:7:"Third Subfield";

2) the name of the key you want to use.

Have it return the value.

Create three new columns that use PHP code in your view, and pass the appropriate arguments to your module/theme.

2
  • Being a newbie, I am not sure how to return the value to Views, so, I was trying to use Views PHP module, to apply the code directly to views field.
    – user12947
    Commented Mar 18, 2014 at 19:45
  • that would work too, you'd just be duplicating the code in each PHP column and echo'ing the result, rather than returning it.
    – jdu
    Commented Mar 18, 2014 at 19:53

Your Answer

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