Bagaimana cara mendapatkan nilai input kode pendek di dalam filter?

9

Saya mencoba untuk mendapatkan nilai input dari kode pendek di dalam fungsi yang digunakan oleh filter, tetapi tampaknya tidak berhasil. Inilah yang saya lakukan:

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

Sekarang saya tahu menggunakan $valuedi dalam filter_value()tidak akan berfungsi karena lingkup variabel, tetapi bahkan menggunakan $GLOBALS['value']tidak berfungsi.

Saya bahkan mencoba menggunakan $value = $atts['id']di dalam filter_value();tetapi tidak berhasil juga.

Bagaimana saya bisa menggunakan kode pendek saya suka [my-shortcode id='123']dan meneruskan nilai 123 ke filter?

Terima kasih.

Jack Johansson
sumber

Jawaban:

7

Menggunakan variabel global akan berhasil. Ini sebuah demonstrasi:

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

Catatan tambahan, menyatakan suatu fungsi di dalam fungsi lain bukanlah praktik yang baik .

Dave Romsey
sumber
Ini sebenarnya aneh. Jika saya mengatur nilai menggunakan $GLOBALS['value'] = some valuedan kemudian panggilan $GLOBALS['value']itu berfungsi, tetapi jika saya mengatur nilai langsung $value = some valuedan kemudian menyebutnya menggunakannya $GLOBALS['value']tidak berfungsi, sementara itu harus bekerja sesuai dengan manual PHP.
Jack Johansson
Anda harus mengatur $valueruang lingkup global global $value;sebelum menginisialisasi nilai. Misalnya global $value; $value = $a['id']; Lalu di filter yang dapat Anda lakukan global $value; echo $value;Apakah itu membantu?
Dave Romsey
Ya terima kasih. Saya membaca ini di manual, dan dalam contoh pertama nilai-nilai didefinisikan secara langsung. Apakah saya harus mendefinisikannya di luar fungsi APA PUN yang tersedia secara langsung $GLOBALS['value'];?
Jack Johansson
2
Keren. senang kami mendapatkannya. Dalam contoh pertama dari dokumen-dokumen itu, variabel dinyatakan di luar fungsi dan dalam lingkup global. Jadi, tidak perlu globalkata kunci. Dalam contoh kami, kami telah bekerja dari dalam lingkup fungsi, sehingga globalkata kunci diperlukan.
Dave Romsey
1
Penyaring adalah teman kita! :-) Saya yakin beberapa penjawab yang bersemangat akan ada untuk menjawab pertanyaan Anda jika Anda memerlukan lebih banyak bantuan!
Dave Romsey
7

Berikut adalah beberapa solusi:

Pendekatan # 1

Anda bisa membungkus definisi kode pendek dan posts_wherepanggilan balik filter dalam kelas untuk dapat memberikan nilai yang diberikan antara metode kelas misalnya sebagai variabel pribadi .

Pendekatan # 2

Pendekatan lain adalah dengan meneruskan nilai sebagai input ke WP_Querydalam panggilan balik kode pendek Anda:

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

dan kemudian dalam filter posts_where Anda, Anda dapat mengaksesnya:

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

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

    return $where;

}, 10, 2 );

Pendekatan # 3

... atau Anda juga dapat menyesuaikan contoh dengan @the_dramatist untuk dapat menghapus callback sesudahnya dengan menetapkan fungsi anonim ke variabel:

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

Periksa misalnya dokumen PHP tentang cara menetapkan fungsi anonim, dengan kata kunci penggunaan, ke variabel.

ps: Saya pikir saya pertama kali belajar tentang trik penetapan variabel ini oleh @ gmazzap, untuk membuatnya lebih mudah untuk menghapus callback filter anonim.

Semoga ini bisa membantu!

birgire
sumber
Terima kasih birgire, jawaban yang baik dan tepat seperti biasa. Apakah Anda merekomendasikan untuk mendefinisikan suatu fungsi di dalam suatu fungsi daripada menggunakan variabel unik global? Jika ya, bisakah Anda memberi tahu saya alasannya?
Jack Johansson
Itu tidak akan menjadi ide yang baik, jika kita perlu menggunakan kembali fungsi itu dan itu terjebak dalam ruang lingkup fungsi lain dan akan lebih sulit bagi pengembang lain untuk misalnya melewatkan filter dengan panggilan balik anonim. Jadi sebagai plugin formal untuk repo wp.org saya kemungkinan besar akan mencoba untuk memungkinkan pengembang lain untuk menghapus filter semudah mungkin ;-) Saya juga akan secara umum mencoba menghindari menambahkan lebih banyak global, karena mungkin ada berbagai masalah dengan itu pendekatan. Jika kita masuk ke sudut dengan struktur plugin kita, maka mungkin itu tanda untuk menggunakan struktur alternatif, apa pun itu ;-)
birgire
Saya kira saya akan pergi dengan pendekatan ke-3 Anda. Tampaknya bekerja dalam kasus saya. Bersulang!
Jack Johansson
yakin apa pun yang terbaik untuk Anda. Saya mungkin menggunakan # 1 atau # 2 tanpa fungsi apa pun untuk dengan mudah menghapusnya lagi ;-) @JackJohansson
birgire
2
Kami benar-benar dapat meneruskan argumen khusus dan nilainya WP_Queryuntuk menargetkan contoh yang diberikan dan mengaksesnya melalui berbagai filter seperti posts_where, pre_get_postsdan posts_clauses. Itulah yang kami lakukan dalam pendekatan # 2.
birgire
4

Anda bisa menggunakan usekata kunci PHP . Jadi dengan bantuan usekata kunci ini Anda dapat membawa variabel di dalam suatu fungsi. Dan Anda juga dapat menulis fungsi anonim untuk mengurangi kode. Jadi semuanya akan menjadi-

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

Semoga itu bisa membantu.

CodeMascot
sumber
Ini keren, tetapi fungsi anonim sulit dilepaskan.
Dave Romsey
2
Ooh, menghapus fungsi anonim kini telah dibahas oleh @birgire dalam jawaban lain untuk pertanyaan itu. Keren!
Dave Romsey
0

Mengapa tidak melewatkan nilai $ sebagai param?

 function filter_value($value){
        echo $value;
    }

dokumentasi

madalinivascu
sumber