You are here

1 最初的解决办法

admin 的头像
Submitted by admin on 星期六, 2015-09-19 01:22

作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com

但是项目中的实际问题,还是需要解决的。在实际的项目中,章林选择是用了form_alter来解决这个问题。Form_alter我们在前面,Think in Drupal第一集里面的第一章讲的就是这个钩子,它是非常有用的,在这里解决这个问题也是非常有效的。首先确定实体表单的ID,然后通过form_alter为这个表单添加一个验证回调函数,在自己的验证函数里面添加自己的逻辑。原有的代码已经找不到了,我在网络上找了段类似的代码,做了一下改造:

function mymodule_form_alter(&$form, &$form_state, $form_id) { 

  if ($form_id == 'test_node_form') { 

    $form['#validate'] = 'mymodule_custom_validation_handler'; 

  } 

}

 

function mymodule_custom_validation_handler((&$form, &$form_state){

  $length = strlen($form_state['values']['field_testlength']['und']['0']['value'])

  if ($length > 8) { 

    form_set_error("field_testlength']['und']['0']['value", t('长度必须小于等于8')); 

  } 

}

这段程序我没有调试,用的时候,自己需要检查一下。这里需要注意的是,获取字段值的方法:

$form_state['values']['field_testlength']['und']['0']['value']

以及设置错误消息时,第一个参数:

"field_testlength']['und']['0']['value"

另一个需要注意的是,字段的语言属性,['und'],这里究竟是用und还是默认语言,用的时候也需要自己检查一下。

 

我觉得,解决Drupal7下面的字段验证,应该有更好一点的钩子,我便寻找,寻找,终于找到了一个可能工作的钩子。我的解决办法是这样的:

 

/**

 * Implements hook_field_attach_validate().

 */

function field_validation_field_attach_validate($entity_type, $entity, &$errors) {

  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);

  if($entity_type =='node' &&  $bundle = 'test'){

    if($field_text = $entity->field_text){

      if(strlen($field_text['und'][0]['value'])>8){

        $errors['field_text']['und'][0][] = array(

          'error' => 'field_text', 

          'message' => t('length must less than 8.'),

        );

      }

    }

  }

}

这是最原始的测试代码,它仅仅用来说明了hook_field_attach_validate是可以用来解决这个问题。这也是我第一次使用这个钩子函数。而以后,有关Field的验证问题,一直都是通过这个钩子解决的。首先,我觉得这种方式比form_alter高级一点,Dries曾经写过一篇介绍Drupal7的文章,里面就讲到了字段的验证,与表单的验证分离开了,这在Drupal7里面是一个进步。而这种分离,在Drupal8里面还会进一步的改进。我在drupal.org上面贡献了field validation模块以后,曾经有人建议使用Form_alter的形式,但是我没有理他们,还是坚持使用hook_field_attach_validate

另外的值得注意的是,这段代码:

list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);

这是我从别处拷贝过来的。这里根据一个实体对象、还有实体类型,使用entity_extract_ids这个API函数,便可以提取出来它的idvidbundle。这是很有用的,但是有时候,这个API函数并不能正常工作,个别时候,大部分都是可以的。

此外,这个错误消息的设置:

        $errors['field_text']['und'][0][] = array(

          'error' => 'field_text', 

          'message' => t('length must less than 8.'),

        );

这个,我们在第一集的,字段API一章里面介绍过了这个结构。我最初编写的时候,并不知道这两个键的含义,尤其是'error',所以默认把它设置为了字段名字。'message'的含义我是清楚的,用来设置具体的错误消息。

代码并不是一下子就工作了,我还做了很多的调试工作。还是使用原始的drupal_set_messagedebug

有了hook_field_attach_validate,我们便不需要考虑具体的表单ID了,因为内容类型很多,实体类型也很多。我们不可能处理所有的情况,而hook_field_attach_validate可以帮助我们从这个问题中解脱出来。我在选用这个钩子以前,应该读过Field Attach APIhttp://api.drupal.org/api/drupal/modules%21field%21field.attach.inc/group/field_attach/7,以及http://api.drupal.org/api/drupal/modules%21field%21field.module/group/field/7, 当然,我还在api.drupal.org上面搜索相关的钩子函数:

图片1.png 

它的触发函数,field_attach_validate,我应该也读过的:

function field_attach_validate($entity_type, $entity) {

  $errors = array();

  // Check generic, field-type-agnostic errors first.

  _field_invoke_default('validate', $entity_type, $entity, $errors);

  // Check field-type specific errors.

  _field_invoke('validate', $entity_type, $entity, $errors);

 

  // Let other modules validate the entity.

  // Avoid module_invoke_all() to let $errors be taken by reference.

  foreach (module_implements('field_attach_validate') as $module) {

    $function = $module . '_field_attach_validate';

    $function($entity_type, $entity, $errors);

  }

 

  if ($errors) {

    throw new FieldValidationException($errors);

  }

}

我读的时候不够细致,忽略里面的注释。总之,我做了很多的准备工作的。


Drupal版本: