将参数传递给筛选器和操作函数

时间:2012-03-17 作者:Aakash Chakravarthy

是一种将自己的参数传递给中的函数的方法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)

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

默认情况下,这是不可能的。如果你用面向对象的方法来做的话,还有一些变通方法
您可以创建一个类来存储以后要使用的值。

示例:

/**
 * 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\'
    )
);
输出:

enter image description here

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

PHP 5.3+

如果可以使用PHP 5.3或更新版本closures 将使这更容易:

$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>";
}
缺点是不能为闭包编写单元测试 ;

SO网友:wesamly

Use php Anonymous functions:

$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);
SO网友:bob-12345

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

我只想补充一点,通过将实际的doer方法与匿名闭包分离,可以使其更加清晰和灵活。为此,只需从闭包中调用方法,如下所示(修改了@wesamalalem answer中的示例)。

通过这种方式,您可以在用于调用实际实践者的闭包之外,按照您的意愿编写任意长或复杂的逻辑。

// ... 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;
}

SO网友:hornament

使用返回函数所需的参数创建函数。将此函数(匿名函数,也称为闭包)传递给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);

SO网友:Víctor Noir

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

您的代码可能不是OOPneed to remove that filter 之后,如果是您的情况,还有另一种解决方法可供您使用:利用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;
}

SO网友:samjco

您始终可以使用全局变量。。

  global $my_param;

SO网友:Marcos Rezende

尽管直接调用函数,但要以更优雅的方式执行此操作:pass an anonymous function as a callback.

例如:

我只有一个功能来翻译标题、内容和我帖子的摘录。所以,我需要向这个主函数传递一些参数,说明谁在调用。

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 接收任意多的参数,因为我传递了一个匿名函数作为回调。

SO网友:lflier

我同意福霞的上述回答给出了首选方法。但是,当我试图围绕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];

}
我是一个未经培训的开发人员,我严格地在自己的网站上工作,所以请对这个草图持保留态度。这对我来说很有用,但如果我在这里做的事情有什么问题,如果有更有知识的人能指出,我将不胜感激。

SO网友:Thomas Jirasko

在我的OOP解决方案中,我只使用了一个在回调函数中调用的类成员变量。在此示例中,post\\u标题由搜索词过滤:

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

SO网友:T.Todua

如果您创建自己的钩子,下面是一个示例。

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

SO网友:giacoder

我知道时间已经过去了,但我在传递自己的参数时遇到了一些问题,直到我发现add\\u filter中的第四个参数是传递的参数数including 要更改的内容。所以,若传递1个附加参数,则数字应为2 你的情况不是1

add_filter(\'the_content\', \'my_content\', 10, 2, $my_param)
和使用

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

SO网友:Pierre-Verthume Larivière

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

然后my\\u content\\u filter()可以调用my\\u content(),传递它想要的任何参数。

结束

相关推荐

Run shortcode before filters

我的用户在注释中发布代码片段。我为此创建了一个快捷码:function post_codigo($atts,$content=\"\"){ return \'<code>\'.$content.\'</code>\'; } add_shortcode(\'codigo\',\'post_codigo\'); 问题是html在打包到代码标记之前会被过滤掉。我想如果我能在过滤器之前运行短代码,那么我可以使用fun