1

Use case / background:

  • A node type "product".
  • A taxonomy vocabulary "feature". E.g. "color" and "size". (forgive the name, it has nothing to do with the features module)
  • Every product can have up to one value for each feature. E.g. color = green, size = big.

At first, this sounds like I should be using one (single-valued) field per feature, instead of a taxonomy. But this really does not scale, because there are going to be many many features, and new features can be dynamically added.

Another option would be a new entity type or bundle "node feature value". Or a new field type with two database columns, which stores both the tid of the feature, and the value.

But I thought, what if I use a regular text field with a custom widget? I would use the "delta" to store the feature tid, and the text value for the value.

Because, let's face it, the delta would be redundant anyway, if there can be only one value per product x feature.

The only question is, how reliable are the deltas? Can it happen that something will "normalize" the deltas to a regular continuous integer sequence 0..n ?

1

The answer is definitely "no", but it's a hard "no", not engine-dependent like it might appear. Under normal operation, the 0..n delta reset happens before the data is ever sent for storage.

If field values are saved using the API (field_attach_submit() etc), then they're unconditionally run through _field_filter_items():

function _field_filter_items($field, $items) {
  $function = $field['module'] . '_field_is_empty';
  foreach ((array) $items as $delta => $item) {
    // Explicitly break if the function is undefined.
    if ($function($item, $field)) {
      unset($items[$delta]);
    }
  }
  return array_values($items);
}

As you can see, any indices you might have manually set in the $items array will be discarded, and the resulting array will always be indexed 0..n. I don't think Drupal gives you another opportunity to affect that array before the data is persisted.

  • 1
    Oh, very good to know. I managed to save entities with custom field item deltas by directly manipulating the node and then calling node_save(). I could confirm in the database that the custom deltas were saved. But seems that this does not work when saving the entity through a form. – donquixote Mar 10 '16 at 9:38
  • Hmm that's interesting, I think you've identified a core bug there. If the SQL storage module relies on them being 0..n when loading, then all paths to saving the field data (except for direct DB manipulation) should normalise the deltas, if only for consistency. The mongodb module has it the right way round IMO – Clive Mar 10 '16 at 9:42
  • The core sql storage normalizes them on loading. So it does not really "depend" on the deltas being normalized in the database. At least not in the code snippet I was looking at. – donquixote Mar 10 '16 at 12:32
  • But yes, could be considered a core bug, if one time it normalizes, and another time it does not. – donquixote Mar 10 '16 at 12:33
0

Turns out the answer is "no":

/**
 * Implements hook_field_storage_load().
 */
function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {
  [..]
        // Add the item to the field values for the entity.
        $entities[$row->entity_id]->{$field_name}[$row->language][] = $item;

This code from Drupal 7 core, field_sql_storage.module shows that at least some parts of Drupal show no respect for the $delta when loading the entity.

On the other hand, look at this contrib field storage implementation in mongodb, in mongodb_field_storage.module:

/**
 * Implements hook_field_storage_load().
 */
function mongodb_field_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {
  [..]
            $field_values[$language][$delta] = $column_values;

So there are storage engines that do respect the field item delta. But with these two examples, we have to assume that support for the $delta is very inconsistent, and far from reliable.

So for my original problem, there is no way around a custom field type. Too bad..

EDIT: Relation module might be another possible solution.

  • It's actually a bit tighter than that, just putting an answer in... – Clive Mar 10 '16 at 9:18

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.