How to set field default values programatically in Drupal 7

I'd like to share a way to set default values of fields to new nodes (more generally "entities") programatically in Drupal 7.

At the time when Drupal 7 was released, it seems that the APIs of Drupal were not in high demand. So Drupal 7 doesn't provide a full set of APIs to make use of field default values. It uses field default values in a limited case, only when a node creation/edit form is rendered. So there's no sample code in the core which shows how to set default values of fields to nodes programatically.

Here's a sample class which sets field default values to a new node:

namespace Drupal\mymodule\Entity; class EntityDefaultValueSetter { /** * Sets default values of fields to an entity. * * @param \EntityDrupalWrapper * The target entity. We need `entity` module to use this object. */ public function setDefaults(\EntityDrupalWrapper $wrapper) { $entity_type = $wrapper->type(); $bundle = $wrapper->getBundle(); $langcode = $wrapper->info()['langcode'] ?: \LANGUAGE_NONE; $raw = $wrapper->raw(); foreach (field_info_instances($entity_type, $bundle) as $instance) { $field_name = $instance['field_name']; if (empty($raw->{"$field_name"}[$langcode])) { $field = field_info_field($field_name); $items = []; field_default_insert($entity_type, $raw, $field, $instance, $langcode, $items); $raw->{"$field_name"}[$langcode] = $items; } } } }

I often use classes and namespaces in Drupal 7 using xautoload module and used them in the code above. But they're ignorable details.

The point is the function field_default_insert(). This is a function defined in the field module in the core and provides a way to set default values of fields to entities including nodes. Actually this function is defined but not used anywhere in the core itself. It just provides a way to set default values of a field to programmers (though it's not promoted enough). The following is the declaration of the function:

field_default_insert($entity_type, $entity, $field, $instance, $langcode, &$items)

As you may know, some people recommend to use field_get_default_value() to set default values. But field_default_insert() is better since it handles details much better for you than field_get_default_value() does.

We should be careful that field_default_insert() doesn't return a value. It modifies the last argument $items which is passed by reference. So we need to manage to use the function properly like in the above snippet.

Note that the above method setDefaults() targets only new nodes. If you want to manage existing nodes in a same manner, you need to tweak the code a little.