I have built a form using the field API. The function hook_field_widget_form gets called for every field. I have a bit of code that populates a select box but it is being called for every field in the form - see the first 10 lines of the code below.

function mango_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {

  $library = libraries_detect('d3_custom_scripts');
  if($library) {
    $libs = libraries_get_libraries();
    $custom_scripts_path = $libs['d3_custom_scripts'];
    $files = file_scan_directory($custom_scripts_path, '/.*\.js$/');
    $custom_script_list[''] = t('Please select');
    foreach ($files as $file => $info) {
      $custom_script_list[$info->filename] = $info->filename;
  $item =& $items[$delta];
  $element += array(
    '#type' => 'fieldset',

  $element['enabled'] = array(
    '#title' => t('Enabled'),
    '#type' => 'checkbox',
    '#default_value' => isset($item['enabled']) ? $item['enabled'] : '',

  $element['custom_script'] = array(
    '#title' => t('Attach script'),
    '#type' => 'select',
    '#options' => $custom_script_list,
    '#default_value' => isset($item['custom_script']) ? $item['custom_script'] : '',
  return $element;

Is there a ay to only run the code once and pass in the variables into the hook_field_widget_form function so I can avoid calling the same code over and over when I only really need to call it once? Many thanks.


Use built-in caching!

At the beginning of your function, test if results are already prepared in cache:

function mango_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  // Construct cache id. Let's start with function name, as it should eb unique
  $cid = __FUNCTION__;
  // Now let's add a fast hash of everything important. Seems only $items matter
  $cid .= '-' . hash('adler32', serialize($items));
  // Oh, and language, too!
  $cid .= '-' . $langcode;

  // Do we have results for this set of parameters?
  if( $result = cache_get($cid)  ) {
    // We do, return it.
    return $result->data;

At the end of your function, just before you return value, save it to cache:

  cache_set($cid, $element);

That's all. It will not prevent your function from being called, but it will prevent actual computation in it. Just be sure to choose cache id carefully. It must be fast to compute, but avoid collisions well.

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.