9

Is there any way to pass data between operations of a single Batch, when using Batch API ?

for an example, say I have $batch['operations'] as an array like this:

// Basic batch stuff to $batch here.
$batch['operations'] = array(
  array('my_initialize', $xyz),
  array('my_worker', $data),
);

// batch_set, process, etc.

function my_initialize($xyz, &$context) {
  // Can I process something here and pass it to 
  // the operation 2 (my_worker) ?
  // May be some key in $context ?
}

function my_worker($data, &$context) {
  // How I can access some result from the my_initialize() function ?
}

I know I can set $context['sandbox'] but that's related to a second call if I set $context['finished'] = FALSE;

I'm currently storing data (it's some kind of chemistry formula which is expensive to store in the operation itself or calculate before batch_set) in $_SESSION in my_initialize and unset it in finished function but I'm curious is there any better way to do this.

2 Answers 2

15

Thanks David for your answer. But unfortunately $context['sandbox'] values were not retained through operations - they were retained through iterations of the same operation but not between operations.

Interestingly though, I found that $context['results'] values were retained between each operation. I did a simple test using the following module:

<?php 
function mytest_menu() {
  $items = array();
  $items['admin/content/mytest'] = array(
    'title' => 'mytest',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('mytest_form'),
    'access arguments' => array('administer content'),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

function mytest_form() {
  $form = array();

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}

function mytest_form_submit($form, $form_state) {
  $batch = array(
    'title' => t('Working ...'),
    'operations' => array(),
    'finished' => 'mytest_batch_finished',
    'init_message' => t('Starting ...'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('An error occurred during processing'),
    'progressive' => FALSE
  );
  $batch['operations'][] = array('mytest_initialize', array('test data')); 
  $batch['operations'][] = array('mytest_perform', array('different data')); 
  $batch['operations'][] = array('mytest_perform', array('different data')); 
  $batch['operations'][] = array('mytest_perform', array('different data')); 
  batch_set($batch);
  batch_process('admin/content/mytest');
}

function mytest_initialize($d, &$context) {
  dsm($d);
  $context['results']['test'] = 'inti val';
  $context['test']['test'] = 'init val';
}

function mytest_perform ($d, &$context) {
  dsm($context);
  $context['results']['test'] = uniqid();
  $context['test']['test'] = $context['results']['test'];
}

function mytest_batch_finished($success, $results, $operations) {
  dsm($results);
}

After the batch finished, I could see the dsm()'d messages. voilà: values were retained.

enter image description here https://i.stack.imgur.com/tkAXx.png

It seems like only $context['results'] was given to the next operation. Arbitrary keys ($context['my own key'] for example) didn't work.

Hope someone will find this useful :)

PS: *previous not previos (screenshot).

1
  • Perfectly! Using $context['results'] for persisting is the solution. Aug 8, 2022 at 8:43
2

Yes, you simply pass the data in

$context['sandbox'] = 'foo';

and it's preserved between requests.

1
  • 2
    Thanks David. Unfortunately it isn't preserved between requests. I made sure that I pass $context by reference but the second function doesn't get what I set in the sandbox. It was preserved in the second request if I set $context['finished'] = FALSE though.
    – AKS
    Jan 25, 2013 at 2:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.