home » Blog » The Least You Need to Know: The Drupal Batch API or How to Use the Drupal Progress Bar

The Least You Need to Know: The Drupal Batch API or How to Use the Drupal Progress Bar

 Making use of the Drupal progress bar is a relatively easy and straightforward process, finding information on how to do it isn’t. First of all because most people will be searching for variants of ‘progress bar’ when they need to be searching for Batch API instead. The offical docs for the Batch API can be found at https://api.drupal.org/api/drupal/includes%21form.inc/group/batch/7, and while they are a good recource once you have an idea of how to use the Batch API, they can be a little confusing at first.

Have no fear, I’ll get you off the ground and processing your data in batches while a nifty progress bar gets displayed to the user in no time. The code in my example was take from a client project and is being used to import clinic locations from a REST API. I’m removing all the implementation code since it’s largely irelevant, I’ll also skip the process of creating a module and adding a menu item for the batch process start page.

Generally speaking you’ll want to start your processing from a form handler. My form only has one element, the submit button that starts processing:

function clinic_import_form() {
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Run Clinic Import Process'),
);

return $form;
}

The form submit handler is where all the magic happens:

function clinic_import_form_submit($form, &$form_state) {
// Normally you'll have some number of things that need to be processed
$count = _get_clinic_count();

// In the case of importing a feed you'll need to bring in bite sized chunks
// So define the size of the bite, and how many bites it will take.
$items_per_page = 50;
// Round up so you get the partial last page.
$pages = ceil($count/$items_per_page);

// This is where the magic happens.
// Tell Drupal about the batch process.
$batch = array(
'title' => t('Importing Clinics'),
'init_message' => t('Beginning clinic import'),
'progress_message' => t('Imported @current out of @total sets of clinics'),
'error_message' => t('Clinic import failed.'),
);

//Now you have to actually add the processes.
for($i=0; $i<=$pages; $i++) {
$batch['operations'][] = array('_do_clinic_import', array($i,));
}

//When run from a form submit handler this is all you have to do.
batch_set($batch);
}

The specific implementation details will vary depending on what you are doing, but the highlights here are the you have to define a $batch array containing a title and a few messages to display during import. The $batch array also needs to have an array of operations in it. The first each operation is defined by an array containing a function name to call and an array of arguments for the function. You’re essentially queing up a function call by passing the function and the data the function needs. 

Believe it or not, that’s it! Just to give a complete example I’ll give you a couple stub functions for _get_clinic_count and _do_clinic_import just so you can have a complete example:

function _get_clinic_count() {
return 3023;
}

function _do_clinic_import($page) {
return TRUE;
}

You have enough now to create a form, start a batch process, and run through the process. Obviously this doesn’t do anything, but you should see a nice progress bar animation and then get returned to the submission form. Like I said, using the Batch API is easy and straighforward; it’s a nice way to break up long running processes, prevent script timeouts, and give your user a sense of how long a task will take. If you have any questions or comments please leave a comment below or hit me up on Twitter @jmickela.