Designed to
delight
we design & develop
exceptional Drupal websites
The Beatles
 
Designed to
inform
we design & develop
exceptional Drupal websites
 
Designed to
unite
we design & develop
exceptional Drupal websites
SGI UK
 
Designed to
inform
we design & develop
exceptional Drupal websites
 
Designed to
delight
we design & develop
exceptional Drupal websites
 
Designed to
entice
we design & develop
exceptional Drupal websites
 
Designed to
engage
we design & develop
exceptional Drupal websites
 
Designed to
convert
we design & develop
exceptional Drupal websites
 
Designed to
motivate
we design & develop
exceptional Drupal websites
 
Designed to
delight
we design & develop
exceptional Drupal websites
 
Designed to
influence
we design & develop
exceptional Drupal websites
 
Designed to
delight
we design & develop
exceptional Drupal websites
 
Designed to
inform
we design & develop
exceptional Drupal websites
 
Designed to
convert
we design & develop
exceptional Drupal websites
Clovis Canopies
 
Designed to
network
we design & develop
exceptional Drupal websites
 
Designed to
motivate
we design & develop
exceptional Drupal websites
 

Using Batch API in Drupal 7 - Batch API Tutorial

Drupal's batch API processing is awesome and offers two great benefits: -

  1. You can break long tasks into smaller batches, preventing max_execution_time errors
  2. You can give the visitor (or more likely administration or developer) some feedback

Building a batch routine in a custom module requires a minimum of 4 function including the batch function call: -

  1. Call the batch API and tell it which function to build the batch instructions.
  2. The batch builder loop which builds a list of operations for the batch routine to perform. It doesn't call the operation code at this point but purely makes the list of operations.
  3. The function to perform 1 operation in the batch.
  4. A "Finished" function to notify the user when we're finished, or if there is an error.

Let's look through a working example, with some of the actual work code removed as it's not important here. This code was mostly adapted from the excellent "Examples" module collection.

Step 1 - Call the batch API function

This just passes a function name to the batch API. The referenced function should build the array which tells batch API what to do. In our example we have it on a form submit handler.

<?php
/*
* Form Submit handler
*/
function drupology_form_submit($form, $form_state) {
 
batch_set(drupology_associate_audio_tiles_to_songs());
}
?>


Step 2 - Create the list of operations to call when the batch starts

Here we essentially build an array of future function calls, with arguments, and a finished function.

The important thing here is the $operations array so look at that closely. When the batch starts it will loop through that array calling those function names with those arguments.

<?php
/**
* Batch operation: associate audio tiles to each song node.
*/
function drupology_associate_audio_tiles_to_songs() {
 
drupal_set_message('Updating Song Nodes');
 
// load all the "Song Story" nodes
 
$nodes = node_load_multiple(array(), array('type' => "story_song"));
 
$node_count = count($nodes);
 
// build the list of operation functions and function arguments
 
foreach($nodes as $nid=>$node) {
   
// $operations[] = array(<function name>, <array of arguments to pass to function>);
   
$operations[] = array('drupology_associate_audio_tiles_to_song', array($node));
  }
 
// build the batch instructions
 
$batch = array(
   
'operations' => $operations,
   
'finished' => 'drupology_associate_audio_tiles_to_songs_finished',
  );
  return
$batch;
}
?>


Step 3 - Create the operation code

This is the actual operation part - the thing that does the work. The arguments it receives will have come from the $operations[] loop in step 2 above. Note the additional $context argument. This is in additional to the ones we provided in step 2 and lets us converse with the batch. This is useful for passing back status messages, etc.

<?php
/**
* Batch operation: associate audio tiles to 1 node.
* This is the function that is called on each operation in the above.
*/
function drupology_associate_audio_tiles_to_song($node, &$context) {
 
$context['results'][] = $node->nid . ' : ' . check_plain($node->title);
 
// Optional message displayed under the progressbar.
 
$context['message'] = t('Processing song "@title"', array('@title' => $node->title));
 
$updated = FALSE;
 
// .... do the actual work - code removed in this example
 
if ($updated) {
   
node_save($node);
   
$path = drupal_lookup_path("alias", "node/" . $node->nid);
   
drupal_set_message("<a href='/$path'>" . $node->title . "</a> updated.");
  }
}
?>


Step 4 - Create the "Finished" code

Here we let the user know when we've finished and also if there were any errors.

<?php
function drupology_associate_audio_tiles_to_songs_finished($success, $results, $operations) {
  if (
$success) {
   
// Here we could do something meaningful with the results.
    // We just display the number of nodes we processed...
   
drupal_set_message(t('@count songs  processed.', array('@count' => count($results))));
  } else {
   
// An error occurred.
    // $operations contains the operations that remained unprocessed.
   
$error_operation = reset($operations);
   
drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE))));
  }
}
?>