バッチ処理

~ Batch operations 和訳 ~

バッチ処理を設定します。

バッチ処理を設定することによって、PHP のタイムアウトによって途中で中断されることなく、一度の送信で複数のページリクエストにわたって処理されるようなフォームの実装が可能になります。処理の間、ユーザーには処理の進捗状況を示すプログレスバーが表示されます。

この API は主に、フォーム API のワークフローにおいて使いやすいように設計されていますが、必ずしもフォームを使用しないスクリプト (update.php のような) や、単純にページコールバックで使用することもできます(但しページコールバックでの使用は控え目にすべきでしょう)。

例:

<?php
$batch = array(
  'title' => t('Exporting'),
  'operations' => array(
    array('my_function_1', array($account->uid, 'story')),
    array('my_function_2', array()),
  ),
  'finished' => 'my_finished_callback',
  'file' => 'path_to_file_containing_myfunctions',
);
batch_set($batch);
// フォームのサブミットハンドラ以外で必要
// batch_process の設定
batch_process('node/1');
?>

バッチの 'title'、'init_message' 、 'progress_message' 、 もしくは 'error_message' にユーザからの入力文字列を含める場合は、batch_set() をコールする前に check_plain() や filter_xss() 等のフィルター関数で事前にサニタイズしておくことが必要です。さらに $context の 'results' や 'message' など、バッチ処理から返されるメッセージにユーザからの入力文字列を含める場合も同様です。

バッチ処理のサンプル:

<?php
// 指定したタイプ、指定したユーザーのノードをロードする単純な例
function my_function_1($uid, $type, &$context) {
  // $context 配列は実行時のコンテキスト配列を収集します。(読み)
  // カレントオペレーションの「返り値」でもあります。 (書き)
  // 以下のキーが使用できます。 :
  // 'results' (読み / 書き): バッチ処理によってこれまでに収集された
  // 結果の配列です。カレントオペレーションでは現在の結果を追加できます。
  // 'message' (書き): 進捗状況のページに表示されるメッセージです。
  // 以下のキーは反復処理が必要な場合に使用できます。 :
  // 'sandbox' (読み / 書き): 反復処理の間、永続的に使用するデータを
  // 格納する配列で、自由な用途に使用できます。$_SESSION の代わりに
  // 使用することが推奨されます。バッチ処理の間、ユーザーが複数の
  // ウインドウを立ち上げた場合を想定すると、$_SESSION を使うことは
  // 安全ではありません。
  // 'finished' (書き): 処理の進捗状況のパーセンテージを表す 0 と 1 の
  // 間の浮動小数点数です。 1 (もしくは設定なし) は処理が完結したと
  // いうことになり、バッチ処理は次のオペレーションに進みます。

  $node = node_load(array('uid' => $uid, 'type' => $type));
  $context['results'][] = $node->nid . ' : ' . check_plain($node->title);
  $context['message'] = check_plain($node->title);
}

// さらに高度な例: すべてのノードをロードします。そうとう時間がかかり、
// 反復処理が必要な場合です。
function my_function_2(&$context) {
  if (empty($context['sandbox'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_node'] = 0;
    $context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT nid) FROM {node}')->fetchField();
  }
  $limit = 5;
  $result = db_select('node')
    ->fields('node', array('nid'))
    ->condition('nid', $context['sandbox']['current_node'], '>')
    ->orderBy('nid')
    ->range(0, $limit)
    ->execute();
  foreach ($result as $row) {
    $node = node_load($row->nid, NULL, TRUE);
    $context['results'][] = $node->nid . ' : ' . check_plain($node->title);
    $context['sandbox']['progress']++;
    $context['sandbox']['current_node'] = $node->nid;
    $context['message'] = check_plain($node->title);
  }
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}
?>

'finished' コールバックの例:

<?php
function batch_test_finished($success, $results, $operations) {
  // 'success' パラメータはPHP の致命的エラーが検出されなかったことを意味します。
  // その他のエラーマネジメントには 'results' が使用されます。
  if ($success) {
    $message = format_plural(count($results), 'One post processed.', '@count posts processed.');
  }
  else {
    $message = t('Finished with an error.');
  }
  drupal_set_message($message);
  // リダイレクト先のページのデータの提供は $_SESSION を通して行われます。
  foreach ($results as $result) {
    $items[] = t('Loaded node %title.', array('%title' => $result));
  }
  $_SESSION['my_batch_results'] = $items;
}
?>
タグ: 
コア: 
Drupal7