Comment obtenir les valeurs d'entrée de shortcode dans un filtre?

9

J'essaie d'obtenir la valeur d'entrée d'un shortcode dans une fonction qui est utilisée par un filtre, mais il ne semble pas y avoir de succès. Voici ce que j'ai fait:

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

Maintenant, je sais que l'utilisation à l' $valueintérieur filter_value()ne fonctionnera pas à cause des portées variables, mais même l'utilisation $GLOBALS['value']ne fonctionne pas.

J'ai même essayé de l'utiliser $value = $atts['id']à l'intérieur filter_value();mais sans succès non plus.

Comment puis-je utiliser mon shortcode comme [my-shortcode id='123']et passer la valeur 123 au filtre?

Merci.

Jack Johansson
la source

Réponses:

7

L'utilisation d'une variable globale fonctionnera. Voici une démonstration:

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

Remarque, déclarer une fonction dans une autre fonction n'est pas une bonne pratique .

Dave Romsey
la source
C'est vraiment étrange. Si je définit la valeur en utilisant $GLOBALS['value'] = some valueet appelle ensuite $GLOBALS['value']cela fonctionne, mais si je définit directement la valeur en tant $value = some valueque puis l'appelle en utilisant $GLOBALS['value']cela ne fonctionne pas, alors que cela devrait fonctionner selon le manuel PHP.
Jack Johansson
Vous devez définir $valuela portée globale avec global $value;avant de l'initialiser avec une valeur. Par exemple global $value; $value = $a['id']; , dans le filtre, vous pouvez le faire global $value; echo $value;.
Dave Romsey
Oui merci. Je lisais ceci sur le manuel, et dans le premier exemple, les valeurs sont définies directement. Dois-je les définir en dehors de N'IMPORTE QUELLE fonction pour être disponible directement en utilisant $GLOBALS['value'];?
Jack Johansson
2
Cool. heureux de l'avoir obtenu. Dans le premier exemple de ces documents, les variables sont déclarées en dehors d'une fonction et dans la portée globale. Donc, aucun globalmot clé n'est nécessaire. Dans nos exemples, nous avons travaillé dans le cadre des fonctions, donc le globalmot-clé est nécessaire.
Dave Romsey
1
Les filtres sont nos amis! :-) Je suis sûr que certains répondeurs désireux seront là pour répondre à vos questions si vous avez besoin de plus d'aide!
Dave Romsey
7

Voici quelques solutions:

Approche n ° 1

Vous pouvez encapsuler la définition du shortcode et le posts_whererappel du filtre dans une classe pour pouvoir passer une valeur donnée entre les méthodes de classe, par exemple en tant que variable privée .

Approche n ° 2

Une autre approche serait de passer la valeur en entrée WP_Querydans le rappel de votre shortcode:

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

puis dans votre filtre posts_where, vous pouvez y accéder:

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

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

    return $where;

}, 10, 2 );

Approche n ° 3

... ou vous pouvez également ajuster l' exemple par @the_dramatist pour pouvoir supprimer le rappel par la suite en affectant la fonction anonyme à une 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' );   

Vérifiez par exemple les documents PHP sur la façon d'affecter une fonction anonyme, avec le mot-clé use, à une variable.

ps: Je pense que j'ai d'abord entendu parler de cette astuce d'assignation de variables par @gmazzap, pour faciliter la suppression du rappel d'un filtre anonyme.

J'espère que cela aide!

Birgire
la source
Merci birgire, réponse aimable et précise comme toujours. Recommandez-vous de définir une fonction à l'intérieur d'une fonction plutôt que d'utiliser une variable globale unique? Si oui, pourriez-vous me dire pourquoi?
Jack Johansson
Ce ne serait pas une bonne idée, si nous devons réutiliser cette fonction et qu'elle est coincée dans la portée d'une autre fonction et qu'il serait plus difficile pour les autres développeurs, par exemple, d'ignorer le filtre avec des rappels anonymes. Donc, en tant que plugin formel pour le dépôt wp.org, j'essaierais très probablement de permettre aux autres développeurs de supprimer les filtres aussi facilement que possible ;-) J'essaierais également en général d'éviter d'ajouter plus de globaux, car il peut y avoir divers problèmes avec cela approche. Si nous entrons dans un coin avec notre structure de plugin, alors c'est peut-être un signe d'utiliser une structure alternative, quelle qu'elle soit ;-)
birgire
Je suppose que je vais avec votre 3ème approche. Semble fonctionner dans mon cas. À votre santé!
Jack Johansson
bien sûr ce qui vous convient le mieux. Je pourrais aller avec # 1 ou # 2 sans fonction quelconque pour le supprimer facilement à nouveau ;-) @JackJohansson
birgire
2
Nous pouvons réellement transmettre des arguments personnalisés et leurs valeurs à WP_Querypour cibler une instance donnée et y accéder via divers filtres comme posts_where, pre_get_postset posts_clauses. C'est ce que nous faisons dans l'approche # 2.
birgire
4

Vous pouvez utiliser le usemot - clé de PHP . Donc, avec l'aide de ce usemot - clé, vous pouvez apporter une variable dans une fonction. Et vous pouvez également écrire une fonction anonyme pour réduire le code. Donc, le tout sera-

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

J'espère que cela pourra aider.

CodeMascot
la source
C'est cool, mais les fonctions anonymes sont difficiles à décrocher.
Dave Romsey
2
Ooh, la suppression de la fonction anonyme a maintenant été couverte par @birgire dans une autre réponse à la question. Cool!
Dave Romsey
0

Pourquoi ne pas passer la valeur $ comme paramètre?

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

Documentation

madalinivascu
la source