Apply_Filters()对所需的参数进行切片

时间:2019-12-10 作者:Lupus

我正在尝试向WooCommerce订单中的每个退款行添加一个按钮(其功能超出了这个问题的范围,足以说明它需要退款id作为参数)。我发现这些行是在woocommerce\\includes\\admin\\meta Box\\views\\html订单退款中创建的。无法重写的php。然而,有一项行动:

do_action( \'woocommerce_admin_order_item_values\', null, $refund, $refund->get_id() );
这似乎非常适合我的目的,所以我尝试将以下代码添加到函数中。php测试它是否可以工作:

add_filter(\'woocommerce_admin_order_item_values\', \'test_refund_id\');
function test_refund_id($nullvar, $refund, $refund_id) {
    if ( !empty($refund->refunded_by) ){
        echo \'<td>Refund ID: \'.$refund_id.\'</td>\';  
    }
}
我用过if ( !empty($refund->refunded_by) ) 因为woocommerce_admin_order_item_values 在html订单发货中也会被调用。php,html订单项。php和html订购费。php,第二个参数是“order item”对象(而不是“return”对象),因此没有refunded_by 属性和我的指示应该被忽略。

但令我失望的是,我发现了以下错误:

致命错误:Uncaught ArgumentCounter错误:参数太少,无法执行函数test\\u return\\u id(),传入了1个\\wp includes\\class wp hook。php位于第290行,在\\wp content\\themes\\mytheme\\functions中正好需要3个。菲律宾比索:1087

我知道,事实上,我在上面引用的行中传递了三个参数(即null、退款对象和退款id),但我检查了290行附近错误引用的脚本(\\wp includes\\class wp hook.php),我在apply_filters() 功能:

        // Avoid the array_slice if possible.
        if ( $the_[\'accepted_args\'] == 0 ) {
            $value = call_user_func( $the_[\'function\'] );
        } elseif ( $the_[\'accepted_args\'] >= $num_args ) {
            $value = call_user_func_array( $the_[\'function\'], $args );
        } else {
            $value = call_user_func_array( $the_[\'function\'], array_slice( $args, 0, (int) $the_[\'accepted_args\'] ) );
        }
出于测试目的,我尝试临时更改最后一个“else”子句,用原始的参数数组替换“切片”参数数组,从而强制脚本保留所有参数,因此array_slice( $args, 0, (int) $the_[\'accepted_args\'] ) 变得简单$args. 惊喜,惊喜,现在一切顺利!

enter image description here

现在,我很清楚这当然不是一个解决方案,因为我无法编辑核心WP脚本。我只想知道为什么apply_filters() 认为接受的参数小于传递的参数,因此它将参数数组裁剪为仅第一个参数。

提前非常感谢任何想了解这件事的人。

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

发布的脚本存在两个固有问题。我不确定这会解决你的问题,但它太大了,无法在评论中提及。

首先,您需要使用add_action(), add_filter(). 这本身并不是一笔巨大的交易,因为add_action() 只是一个包装add_filter(), 但你仍然应该使用正确的。

另一个问题可能是您传递的参数。

我知道,事实上,我在上面引用的行中传递了三个参数(即null、退款对象和退款id),

实际上,按照你的方式,你没有传递三个参数,你只传递了一个。但您编写的函数需要三个。

你的add_action() 使用所需的$tag$function_to_add 值,但保留可选$priority$accepted_args. 默认值$accepted_args 是“1”,所以无论何时,只要您通过add_action()add_filter(), 你must 定义$accepted_args 价值

按如下方式尝试,注意“3”的最终值-即$accepted_args 告诉它传递多个参数的值:

add_action(\'woocommerce_admin_order_item_values\', \'test_refund_id\', 10, 3 );
function test_refund_id($nullvar, $refund, $refund_id) {
    if ( !empty($refund->refunded_by) ){
        echo \'<td>Refund ID: \'.$refund_id.\'</td>\';  
    }
}

SO网友:Tom J Nowell

关于过滤器和操作的工作原理,这里有一个根本性的误解,这是您思维中的缺陷:

我知道,事实上,有三个论点

更仔细地检查add_actionadd_filter 显示:

add_action( string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1 )
请注意$accepted_args 参数因为它在调用中不存在add_filter 在您的问题中,它默认为1。要获得3个所有参数,需要指定3。这是因为并非所有过滤器都需要所有参数,如果只需要第一个参数,则可以使用其他无法接受所有参数的函数。E、 g.PHP内部数学函数

其他注意事项:

您使用的add_filter, 但这是一个行动,add_action 应用于操作,以及add_filter 对于过滤器,第三方插件是非主题的,这里可以回答您的问题的唯一原因是因为它可以在不了解WooCommerce的情况下回答。关于插件内部如何工作的细节不在这里,您需要将转义添加到$refund_id, 无法逃脱是一个安全漏洞。esc_html 如果要完成这项工作,请不要修改WP堆芯内部构件,快速查看文档几乎总能给出答案

相关推荐

wordpress hooks

我目前正在使用woocommerce主题,Hotel(https://woocommerce.com/products/hotel/).我最近刚刚创建了一个主页和一个博客页面,其解释方式如下:https://www.wpbeginner.com/wp-tutorials/how-to-create-a-separate-page-for-blog-posts-in-wordpress/现在我想做的是:创建一个带有固定元素的主页,这些元素永远不会改变(如照片),然后添加一些动态元素(如博客中的帖子)……假设