激发带有参数的特定钩子或泛型钩子更好?

时间:2015-04-23 作者:veganista

我正在创建一个表单插件来处理开发人员可以使用操作/过滤器连接的表单。

我的插件需要能够使用不同的过滤器集处理不同的表单,我看到了两种方法。

方法1为每种形式的特定挂钩点火。

这样的代码可以在我的插件中称为form:

$formId = \'contact\';
$errors = apply_filters(\'forms_validate_\' . $formId, $errors, $data);
可以这样使用:

add_filter(\'forms_validate_contact\', function($errors, $data){
    if(empty($data[\'name\'])){
        $errors[\'name\'] = \'Name is required\';
    }

    return $errors;
} 10, 2)
方法2将参数传递给调用函数。

这样的代码可以在我的插件中称为form:

$formId = \'contact\';
$errors = apply_filters(\'forms_validate\', $formId, $errors, $data);
可以这样使用:

add_filter(\'forms_validate\', function($formId, $error, $data){
    switch($formId){
        case \'contact\':
            if(empty($data[\'name\'])){
                $errors[\'name\'] = \'Name is required\';
            }
        break;
    }

    return $errors;
}, 10, 3)
WordPress core中有没有解决这类问题的例子?

有没有更好的处理方法?

2 个回复
最合适的回答,由SO网友:adelval 整理而成

在我看来,方法1更加健壮和可扩展。

Method 1: 要添加或删除表单或其他功能,只需添加或删除函数即可。特别是,您可以从其他文件中执行此操作,例如插件的单独模块或其他外部插件。我认为这是对其有利的主要论点:可扩展性和模块化。

Method 2: 为了添加或删除表单或其他功能,您需要修改现有功能,这更容易出现错误。像方法2中的switch语句很容易失控。案例列表可能会很长,而且只要有几个过滤器使用相同的switch语句,就很容易引入bug。例如,您可能需要用于验证、显示要填写的空表单、显示已填写表单的内容、数据库管理等的筛选器,。。。现在你有了一组函数,每个函数都有一个很长的切换用例列表,你必须保持同步。

(我在重力表单的一个流行扩展中有过一些不好的经验-如果你遵守了规则,这并不是不可管理的,例如,在所有函数中保持案例列表的顺序相同,但这也不太好。)

Locating bugs: 使用方法1容易得多:罪魁祸首通常是新添加的过滤器或表单,而不是方法2很长的函数中无意中引入的一些拼写错误。

Examples: 你会在wordpress核心中找到大量方法1的示例(例如。https://developer.wordpress.org/?s=post+type&post_type[]=wp-parser-hook), 但我不记得方法2的任何一个实例。

SO网友:fuxia

使钩子名称特定于它的用途,而不是它的调用位置。不要传递多个参数,因为这不容易扩展。而是传递参数对象。

示例创建带有依赖项注入接口的参数对象:

interface Validation_Parameters {

    public function id();

    public function errors();

    // not a good name …
    public function details();
}

class Form_Validation_Parameters implements Validation_Parameters {

    private $id;

    private $errors;

    private $details;

    public function __construct( $id, $errors, $details ) {

        $this->id      = $id;
        $this->errors  = $errors;
        $this->details = $details;
    }

    public function id() {
        return $this->id;
    }

    public function errors() {
        return $this->errors;
    }

    public function details() {
        return $this->details;
    }
}

$params = new Form_Validation_Parameters( 
    \'contact\',
    new WP_Error(), // should be prepared better.
    [ \'request\' => $_SERVER[\'REQUEST_URI\'] ]
);
现在将其传入过滤器:

$valid = apply_filters( \'form_is_valid\', TRUE, $params );
第三方开发人员现在可以读取它,但不能更改它,因此其他人可以依赖它的结构,因为没有办法损坏它。

add_filter( \'form_is_valid\', function( $bool, Validation_Parameters $params ) {
    // do something and return a value
});

结束

相关推荐

Testing hooks callback

我正在开发一个使用TDD的插件,有一件事我完全没有测试出来,那就是。。。挂钩。我的意思是好的,我可以测试钩子回调,但我如何测试钩子是否真的触发了(自定义钩子和WordPress默认钩子)?我认为一些嘲弄会有所帮助,但我就是想不出我错过了什么。我用WP-CLI安装了测试套件。根据this answer, init 钩子应该触发,但。。。事实并非如此;此外,该代码在WordPress内部工作。根据我的理解,引导程序是最后加载的,所以不触发init是有意义的,所以剩下的问题是:如果触发了挂钩,我该如何测试?谢谢