Wie erhalte ich die Eingabewerte des Shortcodes in einem Filter?

9

Ich versuche, den Eingabewert eines Shortcodes in einer Funktion abzurufen, die von einem Filter verwendet wird, aber es scheint keinen Erfolg zu geben. Folgendes habe ich getan:

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

Jetzt weiß ich, dass die Verwendung von $valueinside filter_value()aufgrund variabler Bereiche nicht funktioniert, aber selbst die Verwendung $GLOBALS['value']funktioniert nicht.

Ich habe sogar versucht, $value = $atts['id']innerhalb der zu verwenden, filter_value();aber auch keinen Erfolg.

Wie kann ich meinen Shortcode wie verwenden [my-shortcode id='123']und den 123-Wert an den Filter übergeben?

Vielen Dank.

Jack Johansson
quelle

Antworten:

7

Die Verwendung einer globalen Variablen funktioniert. Hier ist eine 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;
}

Nebenbei bemerkt, das Deklarieren einer Funktion innerhalb einer anderen Funktion ist keine gute Praxis .

Dave Romsey
quelle
Das ist eigentlich seltsam. Wenn ich den Wert mit $GLOBALS['value'] = some valueund dann aufrufe $GLOBALS['value'], funktioniert es, aber wenn ich den Wert direkt als $value = some valueund dann mit $GLOBALS['value']aufrufe, funktioniert es nicht, während es gemäß PHP-Handbuch funktionieren sollte.
Jack Johansson
Sie müssen $valueden globalen Bereich mit festlegen , global $value;bevor Sie ihn mit einem Wert initialisieren. ZB global $value; $value = $a['id']; Dann können Sie im Filter tun. global $value; echo $value;Hilft das?
Dave Romsey
Ja dank. Ich habe dies im Handbuch gelesen und im ersten Beispiel werden die Werte direkt definiert. Muss ich sie außerhalb JEDER Funktion definieren, um direkt mit verfügbar zu sein $GLOBALS['value'];?
Jack Johansson
2
Cool. Ich bin froh, dass wir es bekommen haben. Im ersten Beispiel aus diesen Dokumenten werden die Variablen außerhalb einer Funktion und innerhalb des globalen Bereichs deklariert. Es wird also kein globalSchlüsselwort benötigt. In unseren Beispielen haben wir im Rahmen der Funktionen gearbeitet, daher ist das globalSchlüsselwort erforderlich.
Dave Romsey
1
Filter sind unsere Freunde! :-) Ich bin sicher, dass einige eifrige Antwortende da sein werden, um Ihre Fragen zu beantworten, wenn Sie weitere Hilfe benötigen!
Dave Romsey
7

Hier sind einige Problemumgehungen:

Ansatz Nr. 1

Sie können die Definition des Shortcodes und den posts_whereRückruf des Filters in eine Klasse einschließen, um einen bestimmten Wert zwischen den Klassenmethoden zu übergeben, z. B. als private Variable.

Ansatz Nr. 2

Ein anderer Ansatz wäre, den Wert als Eingabe an WP_Queryden Rückruf Ihres Shortcodes zu übergeben:

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

und dann können Sie in Ihrem posts_where-Filter darauf zugreifen:

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

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

    return $where;

}, 10, 2 );

Ansatz Nr. 3

... oder Sie können das Beispiel auch von @the_dramatist anpassen , um den Rückruf anschließend zu entfernen, indem Sie die anonyme Funktion einer Variablen zuweisen:

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

Überprüfen Sie beispielsweise in den PHP-Dokumenten, wie Sie einer Variablen eine anonyme Funktion mit dem Schlüsselwort use zuweisen.

ps: Ich glaube, ich habe zuerst von @gmazzap etwas über diesen Trick der Variablenzuweisung gelernt, um das Entfernen des Rückrufs eines anonymen Filters zu vereinfachen.

Ich hoffe es hilft!

Birgire
quelle
Danke birgire, freundliche und präzise Antwort wie immer. Empfehlen Sie, eine Funktion innerhalb einer Funktion über die Verwendung einer globalen eindeutigen Variablen zu definieren? Wenn ja, können Sie mir bitte sagen, warum?
Jack Johansson
Das wäre keine gute Idee, wenn wir diese Funktion wiederverwenden müssen und sie im Bereich einer anderen Funktion steckt und es für andere Entwickler schwieriger wäre, z. B. den Filter mit anonymen Rückrufen zu überspringen. Als formelles Plugin für das Repo von wp.org würde ich höchstwahrscheinlich versuchen, anderen Entwicklern das Entfernen von Filtern so einfach wie möglich zu ermöglichen ;-) Ich würde auch generell versuchen, das Hinzufügen weiterer Globals zu vermeiden, da dies verschiedene Probleme haben kann Ansatz. Wenn wir mit unserer Plugin-Struktur in eine Ecke geraten, dann ist es vielleicht ein Zeichen, eine alternative Struktur zu verwenden, was auch immer das sein mag
;-)
Ich denke, ich gehe mit Ihrem 3. Ansatz. Scheint in meinem Fall zu funktionieren. Prost!
Jack Johansson
sicher, was auch immer für Sie am besten funktioniert. Ich könnte mit # 1 oder # 2 ohne irgendeine Funktion gehen, um es einfach wieder zu entfernen ;-) @JackJohansson
birgire
2
Wir können passieren tatsächlich auf individuelle Argumente und ihre Werte WP_Querywie eine bestimmte Instanz und den Zugriff darauf durch verschiedene Filter zum Ziel posts_where, pre_get_postsund posts_clauses. Das machen wir in Ansatz 2.
Birgire
4

Sie können das useSchlüsselwort von PHP verwenden . Mit Hilfe dieses useSchlüsselworts können Sie also Variablen in eine Funktion einfügen. Außerdem können Sie eine anonyme Funktion schreiben, um den Code zu reduzieren. Das Ganze wird also

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

Ich hoffe, das hilft.

CodeMascot
quelle
Das ist cool, aber anonyme Funktionen lassen sich nur schwer aushaken.
Dave Romsey
2
Oh, das Entfernen der anonymen Funktion wurde jetzt von @birgire in einer anderen Antwort auf die Frage behandelt. Cool!
Dave Romsey
0

Warum nicht den $ -Wert als Parameter übergeben?

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

Dokumentation

madalinivascu
quelle