7.x field.api.php hook_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items)

Define custom presave behavior for this module's field types.

Make changes or additions to field values by altering the $items parameter by reference. There is no return value.

Parameters

$entity_type: The type of $entity.

$entity: The entity for the operation.

$field: The field structure for the operation.

$instance: The instance structure for $field on $entity's bundle.

$langcode: The language associated with $items.

$items: $entity->{$field['field_name']}[$langcode], or an empty array if unset.

Related topics

4 functions implement hook_field_presave()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

file_field_presave in modules/file/file.field.inc
Implements hook_field_presave().
image_field_presave in modules/image/image.field.inc
Implements hook_field_presave().
number_field_presave in modules/field/modules/number/number.module
Implements hook_field_presave().
taxonomy_field_presave in modules/taxonomy/taxonomy.module
Implements hook_field_presave().
2 invocations of hook_field_presave()
field_attach_presave in modules/field/field.attach.inc
Perform necessary operations just before fields data get saved.
user_save in modules/user/user.module
Save changes to a user account or add a new user.

File

modules/field/field.api.php, line 436
Hooks provided by the Field module.

Code

function hook_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  if ($field['type'] == 'number_decimal') {

    // Let PHP round the value to ensure consistent behavior across storage
    // backends.
    foreach ($items as $delta => $item) {
      if (isset($item['value'])) {
        $items[$delta]['value'] = round($item['value'], $field['settings']['scale']);
      }
    }
  }
}

Comments

rszrama’s picture

This hook deserves a disclaimer: because you're editing an $items array that has been passed in by-reference, any changes you make to prepare the data for saving will persist on these items through the remainder of the page request. If you're performing data transformation, this means your data may be incompatible with your API after you've performed a save in the middle of a page request.

As an example, in Drupal Commerce our Price field was storing prices as integers that got converted to decimals on load and changed back to integers on presave. Unfortunately, this meant that when we saved an order or line item in the middle of the page request, every other function that wanted to manipulate or display the price had an integer instead of the actual decimal value that should've been used.

As such, this hook should be used with extreme caution.

valderama’s picture

I think, by using the clone keyword, one can work on a copy of the field item. Or am I missing something?

theunraveler’s picture

Also note that this hook is only called on the module that defines the field. So you can't use it to hook into presave functionality of other modules' fields.

AFAICT, the best hook to use for that is hook_field_attach_presave(), though it a bit tough since the only parameters are $entity_type and $entity.

ivanjaros’s picture

Note that this hook(as many others) may be and will be run more than once. So be aware of that when you are altering the data before Drupal saves them into database.