Mean in green
I'm Kevin. I live in Salem, Mass with my wife and little boy and I build software.

Using Drupals Batch API

Wednesday Apr 22, 2009

I don't know how I went so long without implementing Drupal's Batch API, but finally had a chance to play with it yesterday and had a Drupal Aha! moment. This particular API is very handy and surprisingly easy to implement.

We've been working on a way to synchronize a bunch of development environments using SVN and make it quick to deploy a new install of the site we're working on. The first step was to use the Import/Export module to dump content types, views and taxonomy definitions to text files. This way we could commit them to the repository and quickly build the framework for a fresh install of the site. Just install Drupal, then run the import function for the content types, views and taxonomies.

This was all great until we started exporting complex content types. It turned out that the system would fail if we tried to do more than one at a time, which meant going through the tedious effort of exporting... one... at... a... time.

Batch API to the rescue!

The Batch API module lets you easily set a batch of callbacks that Drupal will run one at a time, thus avoiding script timeouts for laborious tasks. The batch can be naturally set up in your form submit handler, or can be called in any other function by adding one extra line of code. <?php // Set up the Batch API $batch = array('operations' => array(), 'finished' => '', 'title' => t('Exporting to files'), 'init_message' => t('Starting the export'), 'progress_message' => t('Exported @current out of @total'), 'error_message' => t('An error occurred and some or all of the exports have failed.'), ); ?>

Add as many functions to the batch queue as you need: <?php // Add an array declaring the callback function for your // batch process and an array of callback arguments $batch['operations'][] = array('your_batch_function', array($arg1, $arg2)); // add whatever logic you need $batch['operations'][] = array('another_batch_function', array($arg1, $arg2)); ?>

Tell the Batch API that you are finished: <?php if (!empty($batch['operations'])) { batch_set($batch); // batch_process() only needed if not inside a form _submit handler : batch_process(); } ?>

drupal_execute() is not happy

One problem that I ran into along the way was the discovery that drupal_execute() has some compatibility issues with the Batch API. If I tried to use drupal_execute() in my batch callbacks, it would fail. Luckily there was a link to this tip to pause the batch that allowed the batch functions to use drupal_execute() with no complaints. <?php function your_batch_function($arg1, $arg2) { // Pause the batch $batch =& batch_get(); $ref = $batch; $batch = null;

// run your code with drupal_execute()

// Unpause the batch $batch = $ref; } ?>

Batching makes me happy

So, I just got done batch exporting 88 items including 19 super complex content types, 64 views and 4 vocabularies (one containing over 100 terms) and all it only took a few clicks. The Batch API is an amazing time saver. Combining it with some other awesome community tools like Import/Export gives me time to go take a much needed coffee break :)