Form API Drupal 7 —— 在 Drupal 中创建表单
在前几节课程中,我们已经学习了钩子 hook_block_info()、hook_block_view()、hook_menu() 和 hook_permission(),因此我们现在已经能够通过编程方式创建任意数量的页面和区块。而在本节中,我们将学习 Drupal 7 的 Form API,用于创建表单。我们将创建一个用于模块管理的表单,并尽量使用我们已经掌握的钩子来巩固知识。
首先,我们输出 3 个区块,这对你来说应该已经不难了:
function sitemade_block_info(){
$blocks = array(); // 初始化一个空数组
$blocks[1]['info'] = '用户列表'; // 后台显示的区块标题
$blocks[2]['info'] = '节点列表';
$blocks[3]['info'] = '术语列表';
return $blocks; // 返回区块列表
}
function sitemade_block_view($delta = ''){
$block = array(); // 初始化区块数组
switch ($delta){
case 1:
$block['subject'] = '用户'; // 区块标题
$block['content'] = '';
$query = db_select('users', 'u') // 查询用户表
->fields('u', array('uid', 'name'))
->orderBy('u.uid', 'DESC') // 按 UID 倒序
->range(0, 5) // 仅取前 5 个用户
->execute();
$users = $query->fetchAll(PDO::FETCH_ASSOC);
foreach($users as $user){
$block['content'] .='';
}
break;
case 2:
$block['subject'] = '节点';
$block['content'] = '';
$query = db_select('node', 'n')
->fields('n', array('nid', 'title'))
->orderBy('n.nid', 'DESC')
->range(0, 10)
->execute();
$nodes = $query->fetchAll(PDO::FETCH_ASSOC);
foreach($nodes as $node){
$block['content'] .='';
}
break;
case 3:
$block['subject'] = '术语';
$block['content'] = '';
$query = db_select('taxonomy_term_data', 't')
->fields('t', array('tid', 'name'))
->orderBy('t.tid', 'DESC')
->range(0, 10)
->execute();
$terms = $query->fetchAll(PDO::FETCH_ASSOC);
foreach($terms as $term){
$block['content'] .='';
}
break;
}
return $block;
}
清除缓存以便让新建区块出现在后台。然后将这些区块输出到左侧边栏:

接下来我们创建一个后台页面,用于管理这三个区块:
function sitemade_permission(){
return array(
'admin content blocks' => array(
'title' => t('管理内容区块'),
'description' => t('节点、用户、术语'),
),
);
}
function sitemade_menu(){
$items = array();
$items['admin/config/content/content_blocks'] = array(
'title' => '用户、节点、术语区块',
'description' => '区块管理',
'page callback' => '_sitemade_content_blocks',
'access arguments' => array('admin content blocks'),
);
return $items;
}
function _sitemade_content_blocks(){
$content = 'Lorem ipsum!';
return $content;
}
创建的页面应该在 admin/config/content/content_blocks 地址出现:

接着,我们为管理员添加查看该页面的权限(这就是我们实现 hook_permission() 的原因)。

接下来我们修改代码,创建一个管理表单。我们将在表单中配置区块标题以及显示的实体数量(节点、用户、术语)。
首先修改 hook_menu 的 'page callback' 属性:
function sitemade_menu(){
$items = array();
$items['admin/config/content/content_blocks'] = array(
'title' => '用户、节点、术语区块',
'description' => '区块管理',
'page callback' => 'drupal_get_form',
'page arguments' => array('_sitemade_content_blocks'),
'access arguments' => array('admin content blocks'),
);
return $items;
}
drupal_get_form($form_id)
drupal_get_form() 是 drupal_build_form() 的封装,用于在不需要 $form_state 的情况下调用。
参数说明
- $form_id:表单的唯一标识符。
- 任何其他参数都会传递给对应的表单构建函数。
返回值
返回表单数组。
因此我们需要重写函数 _sitemade_content_blocks() 以返回表单数组:
function _sitemade_content_blocks(){
$form = array();
$form['nodes-title'] = array(
'#type' => 'textfield',
'#title' => t('节点区块标题'),
'#default_value' => variable_get('node_block', ''),
'#size' => 60,
'#maxlength' => 64,
'#description' => t('节点区块的标题'),
);
$form['node-selected'] = array(
'#type' => 'select',
'#title' => t('节点数量'),
'#options' => array(1 => t('1'), 2 => t('2'), 3 => t('3'), 4 => t('4'), 5 => t('5'), 6 => t('6'), 7 => t('7'), 8 => t('8'), 9 => t('9'), 10 => t('10')),
'#default_value' => variable_get('node_block_range', 5),
'#description' => t('显示在区块中的节点数量'),
);
...
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('保存'),
);
return $form;
}
最终我们得到一个如下的后台表单:

表单已经渲染,现在我们添加提交处理函数。使用钩子 hook_formID_validate() 和 hook_formID_submit() 分别用于验证和保存数据。
表单生成与提交
Drupal 使用 drupal_get_form() 来生成和处理表单,也可以使用 drupal_form_submit() 在没有用户交互的情况下提交表单。
下面是一个示例:
$form = drupal_get_form('my_module_example_form');
...
function my_module_example_form($form, &$form_state) {
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('提交'),
);
return $form;
}
function my_module_example_form_submit($form, &$form_state) {
// 表单处理逻辑
}
现在我们为表单添加提交处理逻辑,使其保存表单数据到 Drupal 变量:
function sitemade_content_blocks_submit($form, &$form_values){
variable_set('node_block', $form_values['values']['nodes-title']);
variable_set('user_block', $form_values['values']['users-title']);
variable_set('term_block', $form_values['values']['terms-title']);
variable_set('node_block_range', $form_values['values']['node-selected']);
variable_set('user_block_range', $form_values['values']['user-selected']);
variable_set('term_block_range', $form_values['values']['term-selected']);
}
表单现在可以正常保存数据。提交后值会保存在 Drupal 变量中(使用 variable_set),默认值则通过 variable_get 读取。

最后修改 hook_block_view(),使其从变量中读取标题和显示数量:
function sitemade_block_view($delta = ''){
$block = array();
switch ($delta){
case 1:
$block['subject'] = variable_get('user_block', '用户');
$block['content'] = '';
$query = db_select('users', 'u')
->fields('u', array('uid', 'name'))
->orderBy('u.uid', 'DESC')
->range(0, variable_get('user_block_range', 5))
->execute();
$users = $query->fetchAll(PDO::FETCH_ASSOC);
foreach($users as $user){
$block['content'] .='';
}
break;
case 2:
$block['subject'] = variable_get('node_block', '节点');
$block['content'] = '';
$query = db_select('node', 'n')
->fields('n', array('nid', 'title'))
->orderBy('n.nid', 'DESC')
->range(0, variable_get('node_block_range', 5))
->execute();
$nodes = $query->fetchAll(PDO::FETCH_ASSOC);
foreach($nodes as $node){
$block['content'] .='';
}
break;
case 3:
$block['subject'] = variable_get('term_block', '术语');
$block['content'] = '';
$query = db_select('taxonomy_term_data', 't')
->fields('t', array('tid', 'name'))
->orderBy('t.tid', 'DESC')
->range(0, variable_get('term_block_range', 10))
->execute();
$terms = $query->fetchAll(PDO::FETCH_ASSOC);
foreach($terms as $term){
$block['content'] .='';
}
break;
}
return $block;
}
现在返回首页查看效果。别忘了最后一步 —— 清除缓存!
