是将自己的参数传递给add_filteradd_action中的函数的一种方法。例如,请看以下代码:

function my_content($content, $my_param)
{
do something...
using $my_param here ...
return $content;
}
add_filter('the_content', 'my_content', 10, 1);


我可以传递我自己的参数?类似的东西:

add_filter('the_content', 'my_content($my_param)', 10, 1)




add_filter('the_content', 'my_content', 10, 1, $my_param)


评论

您可以使用$ _SESSION来存储和获取参数。

#1 楼

默认情况下,这是不可能的。如果您采用OOP方法,则有一些变通办法。
您可以创建一个类来存储以后要使用的值。

示例:

/**
 * Stores a value and calls any existing function with this value.
 */
class WPSE_Filter_Storage
{
    /**
     * Filled by __construct(). Used by __call().
     *
     * @type mixed Any type you need.
     */
    private $values;

    /**
     * Stores the values for later use.
     *
     * @param  mixed $values
     */
    public function __construct( $values )
    {
        $this->values = $values;
    }

    /**
     * Catches all function calls except __construct().
     *
     * Be aware: Even if the function is called with just one string as an
     * argument it will be sent as an array.
     *
     * @param  string $callback Function name
     * @param  array  $arguments
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function __call( $callback, $arguments )
    {
        if ( is_callable( $callback ) )
            return call_user_func( $callback, $arguments, $this->values );

        // Wrong function called.
        throw new InvalidArgumentException(
            sprintf( 'File: %1$s<br>Line %2$d<br>Not callable: %3$s',
                __FILE__, __LINE__, print_r( $callback, TRUE )
            )
        );
    }
}
<现在,您可以使用任何所需的函数来调用该类–如果该函数存在于某个地方,则将使用您存储的参数来调用该类。

让我们创建一个演示函数…

/**
 * Filter function.
 * @param  array $content
 * @param  array $numbers
 * @return string
 */
function wpse_45901_add_numbers( $args, $numbers )
{
    $content = $args[0];
    return $content . '<p>' . implode( ', ', $numbers ) . '</p>';
}


…并使用一次…

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 1, 3, 5 ) ),
        'wpse_45901_add_numbers'
    )
);


…再次...

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 2, 4, 6 ) ),
        'wpse_45901_add_numbers'
    )
);


输出:





/>关键是可重用性:您可以重用该类(在我们的示例中还可以重用该函数)。

PHP 5.3+

如果可以使用PHP 5.3或以下版本较新的闭包将使操作变得更容易:

$param1 = '<p>This works!</p>';
$param2 = 'This works too!';

add_action( 'wp_footer', function() use ( $param1 ) {
        echo $param1;
    }, 11 
);
add_filter( 'the_content', function( $content ) use ( $param2 ) {
        return t5_param_test( $content, $param2 );
    }, 12
);

/**
 * Add a string to post content
 *
 * @param  string $content
 * @param  string $string This is $param2 in our example.
 * @return string
 */
function t5_param_test( $content, $string )
{
    return "$content <p><b>$string</b></p>";
}


缺点是您无法编写闭包的单元测试。

评论


您不仅可以为应该在WP核心中内置解决方案的问题提供高质量的答案,而且还可以在五个月后回来使用PHP 5.3+闭包示例更新答案。

–亚当
13年11月17日在7:17



很好的答案!但是,以后如何删除该匿名函数创建的过滤器?

– Vinicius Tavares
2014年8月12日下午3:33

@ViniciusTavares您不能。使用前请三思。 :)

– fuxia♦
2014年8月12日上午8:17

但是请注意,如果将匿名函数保存到变量中(例如,$ func = function(),请使用($ param1){$ param1;};和add_action($ func,11);),则可以通过remove_action($ func,11);

– Bonger
15年5月2日在18:49

但是不建议在要发布的插件或主题上使用匿名函数(可以在自己的项目中使用它们)。问题在于您将无法将其摘钩。您决定采用的任何方法以后都应该无法使用。

–Mueyiwa Moses Ikomi
18年2月22日在16:04

#2 楼

使用php匿名函数:

$my_param = 'my theme name';
add_filter('the_content', function ($content) use ($my_param) {
    //$my_param is available for you now
    if (is_page()) {
        $content = $my_param . ':<br>' . $content;
    }
    return $content;
}, 10, 1);


#3 楼

将任意数量的参数传递给WP过滤器和操作的正确,真正简短,最有效的方法是来自@Wesam Alalem,它使用了闭包。

我只想补充一点,通过将实际的doer方法与匿名闭包分开,可以使它更清晰,更灵活。为此,您只需要按如下方式从闭包中调用方法(来自@Wesam Alalem答案的修改示例)。

这样,您可以根据需要在使用的闭包之外按词法编写尽可能长或复杂的逻辑称呼实际的行动者。

// ... inside some class

private function myMethod() {
    $my_param = 'my theme name';
    add_filter('the_content', function ($content) use ($my_param) {
        // This is the anonymous closure that allows to pass 
        // whatever number of parameters you want via 'use' keyword.
        // This is just oneliner.
        // $my_param is available for you now via 'use' keyword above
        return $this->doThings($content, $my_param);
    }, 10, 2);
}

private function doThings($content, $my_param) {
    // Call here some other method to do some more things
    // however complicated you want.
    $morethings = '';
    if ($content = 'some more things') {
        $morethings = (new MoreClass())->get();
    }
    return $my_param . ':<br>' . $content . $morethings;
}


#4 楼

创建具有返回函数的所需参数的函数。将此函数(匿名函数,也称为闭包)传递到wp挂钩。

此处显示了wordpress后端中的管理员通知。

public function admin_notice_func( $message = '')
{
$class = 'error';
    $output = sprintf('<div class="%s"><p>%s</p></div>',$class, $message);
    $func = function() use($output) { print $output; };
    return $func;
}
$func = admin_notice_func('Message');
add_action('admin_notices', $func);


#5 楼

如其他答案所述,默认情况下无法将参数传递给回调函数。 OOP和PHP匿名函数是解决方法,但是:


您的代码可能不是OOP
,之后可能需要删除该过滤器

如果您的情况下,还有另一种解决方法可供您使用:自己使用add_filterapply_filters函数,使要传递的参数在回调函数中可用:

// Workaround to "save" parameter to be passed to your callback function.
add_filter( 'pass_param', function() use ( $param ){ return $param; } );

// Hook your function to filter whatever you want to filter.
add_filter( 'actual_filter', 'myCallback' );

// Your callback function that actually filters whatever you want to filter.
function myCallback()
{
   // Get the param that we were not able to pass to this callback function.
   $param = apply_filters( 'pass_param', '' );

   // Do whatever with the workarounded-passed param so it can be used to filter.
   return $param;
}


#6 楼

我知道时间已经过去了,但是在发现自己的参数add_filter中的第4个参数是传递的参数数量(包括要更改的内容)之前,我在传递自己的参数时遇到了一些问题。因此,如果您传递1个附加参数,则数字应为2,而不是1。

add_filter('the_content', 'my_content', 10, 2, $my_param)


并使用

function my_content($content, $my_param) {...}


评论


您确定可以将第五个参数传递给add_filter吗?根据官方文档,这是不正确的。你测试过答案了吗?请注意传播错误信息。

–plong0
9月23日19:02

这不是它的工作方式,到目前为止,我的测试确认这不是它的工作方式。

–杰克
12月9日在16:52

#7 楼

尽管直接调用函数,但可以采用更优雅的方式:将匿名函数作为回调传递。

例如:

我只有一个函数来翻译标题,内容和摘录。因此,我需要将一些参数传递给该主函数,以说明谁在调用。

add_filter( 'the_title', function( $text ) { 
    return translate_text( $text, 'title', 'pl' );
});

add_filter( 'the_content', function( $text ) { 
    return translate_text( $text, 'content', 'pl' );
});

add_filter( 'the_excerpt', function( $text ) { 
    return translate_text( $text, 'excerpt', 'pl' );
});


所以,主函数translate_text接收了我想要的尽可能多的参数,只是因为我已经传递了一个匿名函数作为回调。

#8 楼

我同意上述fuxia的答案给出了首选方法。但是,当我尝试着围绕OOP解决方案时,我遇到了一种设置并取消设置过滤器和全局变量的方法:
function my_function() {
    
    // Declare the global variable and set it to something
    global $my_global;
    $my_global = 'something';
        
    // Add the filter
    add_filter( 'some_filter', 'my_filter_function' );
    
    // Do whatever it is that you needed the filter for
    echo $filtered_stuff; 
    
    // Remove the filter (So it doesn't mess up something else that executes later)
    remove_filter( 'some_filter', 'my_filter_function' );

    // Unset the global (Because we don't like globals floating around in our code)
    my_unset_function( 'my_global' );
    
}

function my_filter_function( $arg ) {
    
    // Declare the global
    global $my_global

    // Use $my_global to do something with $arg
    $arg = $arg . $my_global;

    return $arg;

}

function my_unset_function( $var_name ) {

    // Declare the global
    $GLOBALS[$var_name];

    // Unset the global
    unset($GLOBALS[$var_name];

}

我是未经培训的开发人员,我严格在自己的网站上工作,因此请带着一点盐来画这张草图。它对我有用,但是如果我在这里做的事情有问题,请更博学的人指出。

评论


全局变量不受保护:任何人都可以将它们设置为任何值(请考虑命名冲突),并且它们很难调试。通常,它们被视为不良做法。

– fuxia♦
6月22日16:21

#9 楼

在我的OOP解决方案中,我只使用了在回调函数中调用的类成员变量。
在此示例中,post_title由搜索项过滤:
class MyClass
{
  protected $searchterm = '';

  protected function myFunction()
  {
    query = [
      'numberposts' => -1,
      'post_type' => 'my_custom_posttype',
      'post_status' => 'publish'
    ];

    $this->searchterm = 'xyz';
    add_filter('posts_where', [$this, 'searchtermPostsWhere']);
    $myPosts = get_posts($query);
    remove_filter('posts_where', [$this, 'searchtermPostsWhere']);
  }

  public function searchtermPostsWhere($where)
  {
    $where .= ' AND ' . $GLOBALS['wpdb']->posts . '.post_title LIKE \'%' . esc_sql(like_escape($this->searchterm)) . '%\'';
    return $where;
  }
}


#10 楼

您可以随时使用全局变量。.
  global $my_param;


评论


这不能为问题提供答案。一旦拥有足够的声誉,您就可以在任何帖子中发表评论;相反,提供不需要提问者澄清的答案。 -来自评论

– cjbj
17年8月25日在4:25

@cjbj实际上是的。问题是可以将参数传递给add_filter或add_action中的“函数”。尽管这是假设,但用户是否要在add_filter或add_action函数本身中传递它尚不清楚。 :)

– samjco
17年8月25日在5:17



这不是危险。以问题的形式回答更适合评论而不是回答。我相信这就是cjbj正在解决的问题。

–杰克
12月9日在16:40

#11 楼

如果您创建自己的钩子,请参见以下示例。

// lets say we have three parameters  [ https://codex.wordpress.org/Function_Reference/add_filter ]
add_filter( 'filter_name', 'my_func', 10, 3 );
my_func( $first, $second, $third ) {
  // code
}


然后实施钩子:

// [ https://codex.wordpress.org/Function_Reference/apply_filters ]
echo apply_filters( 'filter_name', $first, $second, $third );


评论


这不会将信息从注册传递到回调。它只是说回调可以接受多少个参数。

– fuxia♦
15年5月17日在22:15

@fuxia,您能否建议一个简单的更改,以便信息得到通过?一个会在3之后只是增加参数值吗?

– SherylHohman
19年5月25日在8:32

#12 楼

我希望这样做,但是由于不可能,我想一个简单的解决方法是调用一个不同的函数,例如
add_filter('the_content', 'my_content_filter', 10, 1);

然后my_content_filter()可以调用my_content()传递任何参数它想要。