我们在前面提到,一组处理又被称为一个批处理集。批处理API可以处理多个批处理集,而无须混合它们。可以按照先后顺序来处理多个批处理集,同时为每个批处理集使用一个新的进度指示器。
让我们钻研一个例子。这里我们没有把它放在安装轮廓中,而是把它写在了一个单独的模块中了。这样,当你测试、调试、使用它时,就不需要每次都清空数据库和重新安装Drupal了。记住,只要稍作修改,你就可以在安装轮廓中使用这种方式了,比如,在一个自定义的轮廓任务中,可以使用批处理来响应显示给用户的表单。
对于我们的场景,让我们使用最常见的例子,客户想将一个网站从自定义的内容管理系统迁移到Drupal中来。在原有的数据库中已经有了一个存储用户的数据库表,在我们导出的SQL中,它的样子应该是这样:
CREATE TABLE old_users (
user_id int(32) NOT NULL,
username varchar(32) NOT NULL,
email varchar(32) NOT NULL,
pass varchar(32) NOT NULL
);
INSERT INTO old_users VALUES (3, 'mary', 'mary@example.com', 'foo');
INSERT INTO old_users VALUES (4, 'joe', 'joe@example.com', 'bar');
INSERT INTO old_users VALUES (6, 'fred', 'fred@example.com', 'zou');
INSERT INTO old_users VALUES (7, 'betty', 'betty@example.com', 'baz');
INSERT INTO old_users VALUES (8, 'friedrich', 'freidrich@example.com', 'fre');
INSERT INTO old_users VALUES (9, 'martin', 'martin@example.com', 'aoi');
INSERT INTO old_users VALUES (10, 'fozzie', 'fozzie@example.com', 'lii');
INSERT INTO old_users VALUES (11, 'steve', 'steve@example.com', 'doi');
让我们设立一个批处理,当管理员点击如图23-5所示的表单时,它将把这些用户作为Drupal用户导入进来。

图 23-5.用来选择一次导入多少用户的表单
下面是我们模块的.info文件,我们应该把它放在sites/all/modules/custom/importusers/importusers.info:
; $Id$
name = Import Users
description = Imports users from a database using the batch API.
package = Pro Drupal Development
core = 6.x
我们将首先实现菜单钩子,创建表单定义,和为表单定义编写处理器。sites/all/modules/custom/importusers/importusers.module的初始代码如下:
<?php
// $Id$
/**
* @file
* Example of using the batch API.
*/
/**
* Implementation of hook_menu().
*/
function importusers_menu() {
$items['importusers'] = array(
'title' => 'Import users',
'page callback' => 'drupal_get_form',
'page arguments' => array('importusers_form'),
'access arguments' => array('administer users'),
);
return $items;
}
/**
* Menu callback: define form to begin user importation.
*/
function importusers_form() {
$form['size'] = array(
'#type' => 'select',
'#title' => t('Import how many users per pass?'),
'#description' => t('Choose a value and click the Begin button.'),
'#options' => drupal_map_assoc(array(1, 5, 10, 25, 50)),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Begin'),
);
return $form;
}
/**
* Handle form submission by beginning batch operation.
*/
function importusers_form_submit($form_id, &$form_state) {
$size = $form_state['values']['size'];
$batch = array(
'operations' => array(
array('importusers_import', array($size)),
array('importusers_optimize', array()),
),
'finished' => 'importusers_finished',
'title' => t('Importing Users'),
'init_message' => t('The user import process is beginning.'),
'progress_message' => t('Imported @current of @total.'),
'error_message' => t('The importation process encountered an error.'),
);
batch_set($batch);
// batch_process() not needed here because this is a form submit handler;
// the form API will detect the batch and call batch_process() automatically.
}
对于菜单钩子和表单定义函数,我们应该已经很熟悉了(如果不熟悉的话,那么可以分别参看第4章和第10章)。这里值得注意的地方是importusers_form_submit()函数,我们在它里面定义了我们的批处理集。一个批处理集,在它的关联数组中可以使用以下键。这里只有operations键是必须的。
• operations: 这是一个数组的数组。每个数组包含两个成员:回调函数的名字,和执行操作时传递给回调函数的参数。
• finished: 当所有的操作都完成时调用的回调函数的名字。这个函数将接收在处理期间所发生的事件信息,这样可以通过drupal_set_message()对它进行分析、总结,或者在其它方面使用这些信息。
• title: 这是为用户显示进度信息的页面的标题。如果没有设置title的话,那么将使用t('Processing')。
• init_message:当批处理集的处理进行到初始化时,将会显示这个消息。如果没有设置init_message的话,那么将使用t('Initializing')。
• progress_message:在批处理集的处理期间,显示的消息。在进度消息中可以使用以下占位符:@current, @remaining, @total, 和@percent。随着批处理集的不断处理,这些值也会随之变化。如果没有设置progress_message的话,那么将使用t('Remaining @remaining of @total.')。
• error_message: 在处理期间当发生错误时,显示给用户的消息。如果没有设置error_message的话,那么将使用t('An error has occurred.')。
• file:在一个普通的Drupal请求期间,如果operations和finished的回调函数不在当前范围内,那么必须给出包含这些函数的文件的路径。该路径是相对于Drupal安装的base_path()的,可以使用drupal_get_path()来方便的构建这个路径。如果函数已经位于了范围以内,那么就不需要定义file了。
前面的批处理集是非常简单的,它只包含两个操作.首先,批处理引擎将重复的调用importusers_import($size),直到该函数指出已经导入了所有的用户。记住, $size参数是每次调用所要导入的用户数。$size在这里很重要,这是因为,在批处理API让客户初始化另一个HTTP请求以前,在每个请求周期内,这个变量决定着工作量的大小。例如,如果你有100个用户需要导入,将$size设置为1将会产生100个HTTP请求;而将$size设置为50,那么将会产生2个HTTP请求。在每个请求中,你想要执行的工作量,是由你的服务器的强大程度、服务器的繁忙程度、总工作量的大小共同决定的。