如何在过滤器中获取shortcode的输入值?


9

我正在尝试在过滤器使用的函数中获取简码的输入值,但似乎没有成功。这是我所做的:

function my_shortcode_function($atts){
    $value = $atts['id'];
    function filter_value(){
        echo $value;
    }
    add_filter('posts_where','filter_value');
}
add_shortcode('my-shortcode','my_shortcode_function');

现在我知道,由于变量范围的原因,$value内部使用filter_value()将不起作用,但是即使使用$GLOBALS['value']也不起作用。

我什至尝试$value = $atts['id']在内部使用,filter_value();但也没有成功。

我该如何使用类似我的短代码[my-shortcode id='123']并将123值传递给过滤器?

谢谢。

Answers:


7

使用全局变量将起作用。这是一个示范:

function wpse_shortcode_function( $atts ){
    // User provided values are stored in $atts.
    // Default values are passed to shortcode_atts() below.
    // Merged values are stored in the $a array.
    $a = shortcode_atts( [
                'id'   => false,
    ], $atts );

    // Set global variable $value using value of shortcode's id attribute.
    $GLOBALS['value'] = $a['id'];

    // Add our filter and do a query.
    add_filter( 'posts_where', 'wpse_filter_value' );

    $my_query = new WP_Query( [
        'p' => $GLOBALS['value'],
    ] );

    if ( $my_query->have_posts() ) {
        while ( $my_query->have_posts() ) {
            $my_query->the_post();
            the_title( '<h1>', '</h1>');
        }
        wp_reset_postdata();
    }

    // Disable the filter.
    remove_filter( 'posts_where', 'wpse_filter_value' );
}
add_shortcode( 'my-shortcode', 'wpse_shortcode_function' );

function wpse_filter_value( $where ){
    // $GLOBALS['value'] is accessible here.

    // exit ( print_r( $GLOBALS['value'] ) );

    return $where;
}

注意,在另一个函数中声明一个函数不是一个好习惯


这实际上很奇怪。如果我使用来设置值$GLOBALS['value'] = some value,然后调用$GLOBALS['value']它,它确实起作用,但是如果我直接将值设置为$value = some value,然后使用$GLOBALS['value']它来调用它,则不起作用,尽管它应该按照PHP手册工作。
杰克·约翰逊

您必须先使用设置$value全局范围,global $value;然后再使用值进行初始化。例如,global $value; $value = $a['id']; 然后您可以在过滤器中这样做global $value; echo $value;有帮助吗?
Dave Romsey

对了谢谢。我正在读说明书上,和在第一示例中的值被直接限定。我是否必须在ANY函数之外定义它们才能直接使用$GLOBALS['value'];
杰克·约翰逊

2
凉。我们很高兴。在这些文档的第一个示例中,变量是在函数外部和全局范围内声明的。因此,不需要global关键字。在我们的示例中,我们一直在函数范围内进行工作,因此global关键字是必需的。
Dave Romsey

1
过滤器是我们的朋友!:-)如果您需要更多帮助,我敢肯定会有一些急切的回答者会回答您的问题!
Dave Romsey

7

以下是一些解决方法:

方法1

您可以将短代码的定义和posts_where过滤器的回调包装在一个类中,以便能够在类方法之间传递给定值,例如作为私有变量。

方法#2

另一种方法是通过值作为输入到WP_Query你的简码的回调中:

$query = new WP_Query ( [ 'wpse_value' => 5, ... ] );

然后在posts_where过滤器中可以访问它:

add_filter( 'posts_where', function( $where, \WP_Query $query )
{

    if( $value = $query->get( 'wpse_value' ) )
    {
        // can use $value here
    }

    return $where;

}, 10, 2 );

方法#3

...或者您也可以通过@the_dramatist 调整示例,以便能够通过将匿名函数分配给变量来删除回调:

function my_shortcode_function( $atts, $content )
{
    // shortcode_atts stuff here

    $value = 5; // just an example  

    // Add a filter's callback
    add_filter( 'posts_where',  $callback = function( $where ) use ( $value ) {
        // $value accessible here
        return $where;
    } );

    // WP_Query stuff here and setup $out

    // Remove the filter's callback
    remove_filter( 'posts_where', $callback );

    return $out;
}

add_shortcode( 'my-shortcode', 'my_shortcode_function' );   

查看PHP文档,了解如何使用use关键字将匿名函数分配给变量。

ps:我想我首先通过@gmazzap了解了此变量分配技巧,以使删除匿名过滤器的回调更加容易。

希望能帮助到你!


一如既往地感谢birgire,友好而准确的答案。您是否建议通过使用全局唯一变量在函数内部定义函数?如果可以,请您告诉我为什么?
杰克·约翰逊

如果我们需要重用该函数并将其卡在另一个函数的作用域内,那么这将不是一个好主意,而其他开发人员更难于例如跳过带有匿名回调的过滤器。因此,作为wp.org存储库的正式插件,我很可能会尝试允许其他开发人员尽可能轻松地删除过滤器;-)我通常也将尝试避免添加更多的全局变量,因为这样做可能会出现各种问题方法。如果我们对插件结构
陷入困境

我想我会采用您的第三种方法。似乎在我的情况下工作。干杯!
杰克·约翰逊

确保最适合您的事物。我可能会选择没有任何功能的#1或#2来轻松地再次删除它;-) @JackJohansson
birgire

2
事实上,我们可以通过自定义参数和它们的值,WP_Query通过各种过滤器一样指定某个特定的实例和访问它posts_wherepre_get_postsposts_clauses。这就是我们在方法2中所做的。
birgire

4

您可以使用PHPuse关键字。因此,借助此关键字,您可以将变量带入函数中。而且您还可以编写匿名函数来减少代码。所以整个事情将会是-use

/**
 * How to get shorcode's input values inside a filter?
 *
 * @param $atts
 */
function my_shortcode_function($atts){
    $value = $atts['id'];
    add_filter('posts_where',function() use ( $value ){
        echo $value;
    });

}
add_shortcode('my-shortcode','my_shortcode_function');

希望能有所帮助。


这很酷,但是匿名函数很难解开。
Dave Romsey

2
哦,@ birgire现在已解决此问题的另一个答案,其中提到了删除匿名功能。凉!
Dave Romsey

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.