Wordpress - How to get shortcode's input values inside a filter?

Using a global variable will work. Here's a demonstration:

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

Side note, declaring a function within another function is not a good practice.


Here are few workarounds:

Approach #1

You could wrap the shortcode's definition and the posts_where filter's callback in a class to be able to pass around a given value between the class methods e.g. as a private variable.

Approach #2

Another approach would be to pass the value as an input to WP_Query within your shortcode's callback:

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

and then within your posts_where filter you can access it:

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

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

    return $where;

}, 10, 2 );

Approach #3

...or you could also adjust the example by @the_dramatist to be able to remove the callback afterwards by assigning the anonymous function to a variable:

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

Check e.g. the PHP docs on how to assign an anonymous function, with the use keyword, to a variable.

ps: I think I first learned about this variable assigning trick by @gmazzap, to make it easier to remove an anonymous filter's callback.

Hope it helps!


You can use the use keyword of PHP. So with the help of this use keyword you can bring variable inside a function. And also you can write anonymous function to reduce the code. So the whole thing will be-

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

Hope that helps.