You are here

Drupal专业开发指南 第23章 定义一个批处理集

g089h515r806 的头像
Submitted by g089h515r806 on 星期五, 2009-09-04 11:29

我们在前面提到,一组处理又被称为一个批处理集。批处理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请求期间,如果operationsfinished的回调函数不在当前范围内,那么必须给出包含这些函数的文件的路径。该路径是相对于Drupal安装的base_path()的,可以使用drupal_get_path()来方便的构建这个路径。如果函数已经位于了范围以内,那么就不需要定义file了。
 
    前面的批处理集是非常简单的,它只包含两个操作.首先,批处理引擎将重复的调用importusers_import($size),直到该函数指出已经导入了所有的用户。记住, $size参数是每次调用所要导入的用户数。$size在这里很重要,这是因为,在批处理API让客户初始化另一个HTTP请求以前,在每个请求周期内,这个变量决定着工作量的大小。例如,如果你有100个用户需要导入,将$size设置为1将会产生100个HTTP请求;而将$size设置为50,那么将会产生2个HTTP请求。在每个请求中,你想要执行的工作量,是由你的服务器的强大程度、服务器的繁忙程度、总工作量的大小共同决定的。

Drupal版本: