作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们首先定义菜单项:
$items['breadcrumb/add'] = array(
'title' => 'Add breadcrumb',
'page callback' => 'breadcrumb2_add',
'access arguments' => array('administer breadcrumbs'),
'file' => 'breadcrumb2.admin.inc',
);
接着,向breadcrumb2.admin.inc添加回调函数breadcrumb2_add:
/**
* Returns a breadcrumb submission form.
*/
function breadcrumb2_add(){
$breadcrumb = entity_get_controller('breadcrumb2')->create();
drupal_set_title(t('Create breadcrumb'));
$output = drupal_get_form('breadcrumb2_form', $breadcrumb);
return $output;
}
在这个函数里面,我们首先使用entity_get_controller创建了一个初始化的面包屑,然后设置了标题,最后调用drupal_get_form,调用的表单ID为breadcrumb2_form,同时我们把$breadcrumb传递给了它。我们这样做的目的,是希望breadcrumb2_form同时能够适应于编辑表单。我们来看看breadcrumb2_form的定义:
/**
* The breadcrumb edit form.
*/
function breadcrumb2_form($form, &$form_state, $breadcrumb) {
// Save the breadcrumb for later, in case we need it.
$form['#breadcrumb'] = $breadcrumb;
$form_state['breadcrumb'] = $breadcrumb;
$form['bid'] = array(
'#type' => 'value',
'#value' => isset($breadcrumb->bid) ? $breadcrumb->bid : NULL,
);
// Add the field related form elements.
field_attach_form('breadcrumb2', $breadcrumb, $form, $form_state);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#weight' => 40,
);
if (!empty($breadcrumb->bid)) {
$form['actions']['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete breadcrumb'),
'#weight' => 45,
'#limit_validation_errors' => array(),
'#submit' => array('breadcrumb2_form_submit_delete')
);
}
$form['#validate'][] = 'breadcrumb2_form_validate';
$form['#submit'][] = 'breadcrumb2_form_submit';
return $form;
}
首先,我们将$breadcrumb保存到了$form和$form_state里面,这里保存原始的面包屑对象。接着,我们添加了'bid'元素,它的类型为value,为什么这样做呢?因为有些模块会使用entity_extract_ids来提取实体的ID,在Drupal7里面,如果我们不预先保存一个实体ID的话,entity_extract_ids就会提取不出来,Drupal8已经改进了这个问题,我遇到过这个问题,所以在这里加了了'bid'。接着是使用field_attach_form,把实体上面的字段也添加进来,由于字段的添加,是动态的,我们也不知道具体有几个字段,通过field_attach_form,我们就可以把这个工作委托给Field模块了,它能够帮我们做这件事情。再往下是提交、删除按钮,我们把这两者放到了actions里面了,actions是Drupal7里面的一个新的表单元素类型;对于删除按钮,我们为它指定了一个单独的提交函数breadcrumb2_form_submit_delete,同时为它设置了'#limit_validation_errors',通过这个设置,在删除面包屑的时候,即便是存在验证错误的话,也可以正常提交。最后是为表单设置$form['#validate']、$form['#submit'],我们在第一集里面学过,即便不设置这两行代码,表单系统也会自动使用这两个函数,为什么明确的设置呢?因为我看到其它实体的添加表单都是这样明确设置的,包括节点的添加表单,或许这样做的好处的,代码的可读性更强。
接下来是表单验证函数:
function breadcrumb2_form_validate($form, &$form_state) {
$breadcrumb = $form_state['breadcrumb'];
// Notify field widgets to validate their data.
field_attach_form_validate('breadcrumb2', $breadcrumb, $form, $form_state);
}
代码比较简单,我们模块本身没有多少验证工作,所以这里直接将验证工作委托给了Field模块,这里使用的是field_attach_form_validate。
再往下,是提交函数,逻辑也比较简单:
/**
* Breadcrumb form submit handler.
*/
function breadcrumb2_form_submit($form, &$form_state) {
$breadcrumb = &$form_state['breadcrumb'];
// Notify field widgets.
field_attach_submit('breadcrumb2', $breadcrumb, $form, $form_state);
// Save the breadcrumb
breadcrumb2_save($breadcrumb);
drupal_set_message(t('Breadcrumb saved.'));
$form_state['redirect'] = 'breadcrumb/' . $breadcrumb->bid;
}
我们首先使用field_attach_submit,将提交委托给了Field模块,接着我们调用我们的API函数breadcrumb2_save,保存实体。最后设置一个消息,并重定向。
在这部分,需要注意的是field_attach_form、field_attach_form_validate、field_attach_submit的使用。这里我有个疑问,不知道为什么不把field_attach_submit叫做field_attach_form_submit。
编写完这些代码以后,可以测试一下了,如果你按照这里所列的代码,跟着做的,现在访问breadcrumb/add页面,我们可以看到一个表单页面,这里面包含前面我们添加的两个字段。一切正常。输入一些测试数据,提交,我们遇到了第一个问题:
这是一个PHP错误。我在网上搜索了这个问题,很多人也遇到了同样的问题,但是没有找到答案。我们在开发的过程中,是存在一些问题,这些问题起初我也没有注意到,我也希望一次能够搞定所有的问题,但是错误总是不经意的出现。如果你能够,在现有的代码基础上,把所有的问题都解决掉,那么证明你完全掌握了如何定义一个实体类型。我也是在解决这些问题的过程中,才明白了里面的很多细微的地方。