Jak uzyskać wartości wejściowe shortcode w filtrze?


9

Próbuję uzyskać wartość wejściową shortcode wewnątrz funkcji, która jest używana przez filtr, ale wydaje się, że nie ma sukcesu. Oto co zrobiłem:

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

Teraz wiem, że używanie $valuewewnątrz filter_value()nie będzie działać z powodu zmiennych zakresów, ale nawet używanie $GLOBALS['value']nie działa.

Próbowałem nawet użyć w $value = $atts['id']środku, filter_value();ale też bez powodzenia.

Jak mogę użyć mojego krótkiego kodu [my-shortcode id='123']i przekazać wartość 123 do filtra?

Dzięki.

Odpowiedzi:


7

Korzystanie ze zmiennej globalnej będzie działać. Oto demonstracja:

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

Uwaga dodatkowa: deklarowanie funkcji w ramach innej funkcji nie jest dobrą praktyką .


To jest naprawdę dziwne. Jeśli ustawię wartość za pomocą, $GLOBALS['value'] = some valuea następnie wywołam, $GLOBALS['value']to zadziała, ale jeśli ustawię wartość bezpośrednio jako, $value = some valuea następnie wywołanie przy użyciu $GLOBALS['value']nie zadziała, podczas gdy powinno działać zgodnie z instrukcją PHP.
— Jack Johansson

Przed zainicjowaniem go wartością należy ustawić $valuezakres globalny global $value;. Np. global $value; $value = $a['id']; W filtrze możesz to zrobić global $value; echo $value;Czy to pomaga?
— Dave Romsey

Tak, dziękuję. Czytałem to w instrukcji, aw pierwszym przykładzie wartości są definiowane bezpośrednio. Czy muszę je definiować poza JAKĄKOLWIEK funkcją, aby były dostępne bezpośrednio przy użyciu $GLOBALS['value'];?
— Jack Johansson

2
Fajne. cieszę się, że to mamy. W pierwszym przykładzie z tych dokumentów zmienne są deklarowane poza funkcją i w zakresie globalnym. Tak więc żadne globalsłowo kluczowe nie jest potrzebne. W naszych przykładach pracowaliśmy z zakresu funkcji, więc globalsłowo kluczowe jest konieczne.
— Dave Romsey

1
Filtry są naszymi przyjaciółmi! :-) Jestem pewien, że w pobliżu znajdą się chętni odpowiedzi, aby odpowiedzieć na twoje pytania, jeśli potrzebujesz dodatkowej pomocy!
— Dave Romsey

7

Oto kilka obejść:

Podejście nr 1

Można zawinąć definicję skrótu i posts_wherewywołanie zwrotne filtra w klasę, aby móc przekazywać określoną wartość między metodami klasowymi, np. Jako zmienną prywatną .

Podejście nr 2

Innym podejściem byłoby przekazanie wartości jako danych wejściowych do WP_Querywywołania zwrotnego kodu krótkiego:

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

a następnie w filtrze post_where możesz uzyskać do niego dostęp:

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

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

    return $where;

}, 10, 2 );

Podejście nr 3

... lub możesz także dostosować przykład przez @tam_dramatist, aby móc później usunąć wywołanie zwrotne, przypisując funkcję anonimową do zmiennej:

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

Sprawdź np. Dokumentację PHP, w jaki sposób przypisać anonimową funkcję za pomocą słowa kluczowego use do zmiennej.

ps: Myślę, że po raz pierwszy dowiedziałem się o tej sztuczce przypisywania zmiennych przez @gmazzap, aby ułatwić usunięcie wywołania zwrotnego anonimowego filtra.

Mam nadzieję, że to pomoże!


Dziękuję bardzo, życzliwa i precyzyjna odpowiedź jak zawsze. Czy zaleca się zdefiniowanie funkcji wewnątrz funkcji zamiast używania globalnej zmiennej unikalnej? Jeśli tak, czy możesz mi powiedzieć, dlaczego?
— Jack Johansson

To nie byłby dobry pomysł, gdybyśmy musieli ponownie użyć tej funkcji i utknęła w zasięgu innej funkcji, a innym programistom byłoby trudniej np. Pominąć filtr z anonimowymi wywołaniami zwrotnymi. Więc jako formalna wtyczka do repozytorium wp.org najprawdopodobniej postaram się pozwolić innym programistom na usunięcie filtrów tak łatwo, jak to możliwe ;-) Ogólnie starałbym się również unikać dodawania większej liczby globali, ponieważ mogą być z tym różne problemy podejście. Jeśli wejdziemy w kąt z naszą strukturą wtyczek, być może jest to znak, aby użyć alternatywnej struktury, cokolwiek to może być ;-)
— birgire

Chyba wybieram twoje trzecie podejście. Wydaje się działać w moim przypadku. Twoje zdrowie!
— Jack Johansson

na pewno cokolwiek będzie dla ciebie najlepsze. Mogę przejść z numerem 1 lub nr 2 bez żadnej innej funkcji, aby łatwo go ponownie usunąć ;-) @JackJohansson
— birgire

2
Możemy faktycznie przejść na własnych argumentów i ich wartości do WP_Querykierowania danej instancji i do niego dostęp za pomocą różnych filtrów, takich jak posts_where, pre_get_postsi posts_clauses. To właśnie robimy w podejściu nr 2.
— birgire

4

Możesz użyć usesłowa kluczowego PHP . Tak więc za pomocą tego usesłowa kluczowego można wprowadzić zmienną do funkcji. A także możesz napisać anonimową funkcję, aby zmniejszyć kod. Więc cała sprawa będzie-

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

Mam nadzieję, że to pomaga.


To fajne, ale anonimowe funkcje są trudne do odblokowania.
— Dave Romsey

2
Ooh, usunięcie anonimowej funkcji zostało teraz objęte przez @birgire w innej odpowiedzi na pytanie. Fajne!
— Dave Romsey

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.