You are here

function batch_example_update_8001 in Examples for Developers 8

Same name and namespace in other branches
  1. 3.x modules/batch_example/batch_example.install \batch_example_update_8001()

Example of batch-driven update function.

Because some update functions may require the batch API, the $sandbox provides a place to store state. When $sandbox['#finished'] == TRUE, calls to this update function are completed.

The $sandbox param provides a way to store data during multiple invocations. When the $sandbox['#finished'] == 1, execution is complete.

This dummy 'update' function changes no state in the system. It simply loads each node.

To make this update function run again and again, execute the query "update system set schema_version = 0 where name = 'batch_example';" and then run /update.php.

Related topics

File

batch_example/batch_example.install, line 27
Install, update, and uninstall functions for the batch_example module.

Code

function batch_example_update_8001(&$sandbox) {
  $db_connection = \Drupal::database();

  // Use the sandbox at your convenience to store the information needed
  // to track progression between successive calls to the function.
  if (!isset($sandbox['progress'])) {

    // The count of nodes visited so far.
    $sandbox['progress'] = 0;

    // Total nodes that must be visited.
    $sandbox['max'] = $db_connection
      ->query('SELECT COUNT(nid) FROM {node}')
      ->fetchField();

    // A place to store messages during the run.
    $sandbox['messages'] = [];

    // Last node read via the query.
    $sandbox['current_node'] = -1;
  }

  // Process nodes by groups of 10 (arbitrary value).
  // When a group is processed, the batch update engine determines
  // whether it should continue processing in the same request or provide
  // progress feedback to the user and wait for the next request.
  $limit = 10;

  // Retrieve the next group of nids.
  $query = $db_connection
    ->select('node', 'n');
  $query
    ->fields('n', [
    'nid',
  ]);
  $result = $query
    ->where('n.nid > :nid', [
    ':nid' => $sandbox['current_node'],
  ])
    ->range(0, $limit)
    ->orderBy('n.nid', 'ASC')
    ->execute();
  foreach ($result as $row) {

    // Here we actually perform a dummy 'update' on the current node.
    $node = $db_connection
      ->query('SELECT nid FROM {node} WHERE nid = :nid', [
      ':nid' => $row->nid,
    ])
      ->fetchField();

    // Update our progress information.
    $sandbox['progress']++;
    $sandbox['current_node'] = $row->nid;
  }

  // Set the "finished" status, to tell batch engine whether this function
  // needs to run again. If you set a float, this will indicate the progress
  // of the batch so the progress bar will update.
  $sandbox['#finished'] = $sandbox['progress'] >= $sandbox['max'] ? TRUE : $sandbox['progress'] / $sandbox['max'];

  // Set up a per-run message; Make a copy of $sandbox so we can change it.
  // This is simply a debugging stanza to illustrate how to capture status
  // from each pass through hook_update_N().
  $sandbox_status = $sandbox;

  // Don't want them in the output.
  unset($sandbox_status['messages']);
  $sandbox['messages'][] = t('$sandbox=') . print_r($sandbox_status, TRUE);
  if ($sandbox['#finished']) {

    // hook_update_N() may optionally return a string which will be displayed
    // to the user.
    $final_message = '<ul><li>' . implode('</li><li>', $sandbox['messages']) . "</li></ul>";
    return t('The batch_example demonstration update did what it was supposed to do: @message', [
      '@message' => $final_message,
    ]);
  }
}