You are here

6 field_validation_field_attach_validate

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

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

这里面,最先实现的是field_validation_field_attach_validate,在这个钩子函数中,alpha1版本里面包含两大段注释代码,最下面的那段注释代码,就是我最初测试hook_field_attach_validate所用到的代码,在这个版中还保留着,幸好还保留着,这样可以留下一个成长的轨迹。最上面那段注释里面的代码,是最初的实现代码。把它的格式整理一下:

  // 获取一个bundle上面所有的字段实例.

  $instances = field_info_instances($entity_type, $bundle);

  //debug($instances);

  // 对每个字段实例进行迭代处理,

  foreach ($instances as $instance) {

    $field_name = $instance['field_name'];

    $field = field_info_field($field_name);

    // 获取字段上面可用的语言.

    $languages = field_available_languages($entity_type, $field);

    //对于每个语言进行迭代

    foreach ($languages as $langcode) {

      $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();

      debug($items);

      //查找这个字段实例上面,是否存在验证规则,如果存在验证规则,执行这些验证

      $rules = field_validation_get_field_rules($instance);

      if($rules){

        foreach ($rules as $rule) {

          module_invoke_all("field_validation_validate", $rule['validator'], $items, $rule, $errors);

        }

      }

    }

  }

这段代码也是可以工作的,为什么把它注释掉呢?因为我找到了更好的办法了。没有被注释掉的代码,就是更好的办法。在注释掉的代码中,我们首先获取这个实体上面都有哪些字段,然后对字段循环处理,分别检查每个字段上面是否存在验证规则,如果存在,再进行验证。   

实际上,大部分的字段上面都没有验证规则的,根据字段循环迭代,浪费了。改进的代码,逻辑是这样的,检查这个实体类型上面是否存在验证规则,如果存在,分别对这些规则进行验证,有多少规则验证多少,没有的话,跳过去。具体的代码实现,在后面多次的改进,变更,但是这个基本逻辑,却被保留了下来。这就是我们前面看到的代码,我这里加点注释说明:

 

  //获取bundle上面的所有验证规则,这个函数位于field_validation.rules.inc中,

//是最早实现的函数之一

  $rules = field_validation_get_bundle_rules($entity_type, $bundle);

  if($rules){

    //对于每个规则循环处理

    foreach ($rules as $rule) {

      $field_name = $rule['field_name'];

      $field = field_info_field($field_name);

      $languages = field_available_languages($entity_type, $field);

      foreach ($languages as $langcode) {

        $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();

//这里面仍然使用了module_invoke_all,但是这里是有返回值的,

//我们将返回值赋值给了$errors[$rule['field_name']][$langcode]

//这与最初的实现不同,最初的实现里面,是把$errors传递了过去,

//不过module_invoke_all是无法传递引用的,因此无法正常工作

//我经过调试,调试才通过这个办法解决了这个问题,当然这里还是有问题的

        $errors[$rule['field_name']][$langcode] = module_invoke_all("field_validation_validate", $rule['validator'], $items, $rule);

      }

    }

  }

我开始的时候,是没有意识到module_invoke_all无法传递引用的,这也是为什么我列出field_attach_validate这个API函数源代码的原因,里面的注释,说明了这一点,但是最初的时候,自己没有看注释,或者看的不仔细。实际调试的过程中,才发现问题,最后才恍然大悟。

我在这里,第一次实现了自己的Hook,这是我至今都值得骄傲的事情。很久以前,就想自己定义钩子,一直没有机会。尽管这里的钩子,是借鉴hook_webform_validation_validate而来的,但是终归也是自己第一次定义一个钩子函数,并且后来,还有其他开发者使用了这个钩子函数。


Drupal版本: