フィルター内のショートコードの入力値を取得するにはどうすればよいですか?


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の値をのように使用してフィルターに渡すにはどうすればよいですか?

ありがとう。

回答:


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

はい、ありがとう。私はこれをマニュアルで読んでましたが、最初の例では値が直接定義されています。直接使用できるようにするには、関数の外部でそれらを定義する必要があります$GLOBALS['value'];か?
ジャックヨハンソン

2
涼しい。よかったです。これらのドキュメントの最初の例では、変数は関数の外部でグローバルスコープ内で宣言されています。したがって、globalキーワードは必要ありません。この例では、関数のスコープ内から作業しているため、globalキーワードが必要です。
デイブロムジー2017年

1
フィルターは私たちの友達です!:-)さらに助けが必要な場合は、熱心な回答者が質問に答えてくれると思います!
Dave Romsey、2017年

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

たとえば、useキーワードを使用して無名関数を変数に割り当てる方法については、PHPのドキュメントを確認してください。

PS:匿名フィルターのコールバックを簡単に削除できるように、@ gmazzapによってこの変数割り当てのトリックについて最初に学んだと思います。

それが役に立てば幸い!


いつものように、バージール、親切で正確な答えに感謝します。グローバル一意変数を使用するよりも、関数内で関数を定義することをお勧めしますか?はいの場合、その理由を教えてください。
ジャックヨハンソン

その関数を再利用する必要があり、別の関数のスコープ内でスタックしていて、他の開発者が匿名のコールバックを使用してフィルターをスキップするなどの場合、これは良い考えではありません。そのため、wp.orgリポジトリの正式なプラグインとして、他の開発者ができるだけ簡単にフィルターを削除できるようにしようと思います;-)また、一般に、グローバルの追加を避けようとします。アプローチ。プラグイン構造の隅に入る場合、多分それは何であれ、代替構造を使用することのしるしです;-)
バージィ

私はあなたの3番目のアプローチで行くと思います。私の場合はうまくいくようです。乾杯!
ジャックヨハンソン

あなたに最適なものは何でも確実に。私は#1または#2を使用して、無名の関数を使用せずに簡単に再び削除するかもしれません;-) @JackJohansson
birgire

2
実際にカスタム引数とその値を渡してWP_Query、特定のインスタンスをターゲットにしposts_wherepre_get_postsやのようなさまざまなフィルターを介してそれにアクセスできますposts_clauses。これがアプローチ2で行うことです。
バージィ

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、2017年

2
ああ、匿名関数の削除は、質問に対する別の回答で@birgireによってカバーされています。涼しい!
Dave Romsey、

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.