更好地触发带有参数的特定挂钩或通用挂钩?


8

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

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

方法1

每种形式的特定挂钩的火。

因此,这样的代码可以在我的插件中称为表格:

$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

将参数传递给调用函数。

因此,这样的代码可以在我的插件中称为表格:

$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核心中是否有解决此类问题的示例?

有没有处理这种情况的首选方法?

Answers:


2

我认为方法1更加健壮和可扩展。

方法1:若要添加或删除窗体或其他功能,只需添加或删除功能。特别是,您可以从其他文件(例如插件的单独模块或其他外部插件)执行此操作。我认为这是支持它的主要论点:可扩展性和模块化。

方法2:为了添加或删除表单或其他功能,您需要修改现有功能,这更容易出错。像方法2中的switch语句很容易失控。案例列表可能会很长,一旦您拥有多个具有相同switch语句的过滤器,就很容易引入错误。例如,您可能需要过滤器进行验证,显示要填写的空表格,显示已填写的表格的内容,数据库管理等等。因此,您现在拥有了一堆函数,每个函数都有很长的切换用例列表,您必须保持同步。

(在重力形式的流行扩展方面,我对此有一些不好的经验-如果您受过纪律的约束,这并不是很难处理的,例如,在所有功能中将案件列表保持相同的顺序,但这也不是很漂亮。)

定位错误:使用方法1容易得多:罪魁祸首通常是新添加的过滤器或表单,而不是方法2的很长功能中无意中引入的一些错字。

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


4

使挂钩名称特定于其功能,而不是在调用位置。不要传递多个参数,因为这不容易扩展。而是传递参数对象。

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

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
});

尽管我喜欢您通过过滤器参数的对象的想法,但是我不确定它能否回答我的最初问题。另外,您的意思是:“使钩子名称特定于其功能,而不是在何处调用”在上面的示例中,应将“ forms_validate”钩入以基于传递的$ data来验证表单,我已经修改了问题以使这一点更加清楚
veganista 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.