Come ottenere i valori di input dello shortcode all'interno di un filtro?


9

Sto cercando di ottenere il valore di input di uno shortcode all'interno di una funzione utilizzata da un filtro, ma sembra non esserci successo. Ecco cosa ho fatto:

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

Ora so che usare $valueinside filter_value()non funzionerà a causa di ambiti variabili, ma anche l'utilizzo $GLOBALS['value']non funziona.

Ho anche provato a usare $value = $atts['id']all'interno di filter_value();ma senza successo.

Come posso usare il mio shortcode simile [my-shortcode id='123']e passare il valore 123 al filtro?

Grazie.

Risposte:


7

L'uso di una variabile globale funzionerà. Ecco una dimostrazione:

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

Nota a margine , dichiarare una funzione all'interno di un'altra funzione non è una buona pratica .


Questo è in realtà strano. Se imposto il valore usando $GLOBALS['value'] = some valuee poi lo chiamo $GLOBALS['value']funziona, ma se imposto direttamente il valore come $value = some valuee poi lo chiamo usando $GLOBALS['value']non funziona, mentre dovrebbe funzionare secondo il manuale di PHP.
Jack Johansson

È necessario impostare $valuel'ambito globale con global $value;prima di inizializzarlo con un valore. Ad esempio, global $value; $value = $a['id']; nel filtro puoi fare. global $value; echo $value;Ti aiuta?
Dave Romsey,

Sì grazie. Leggevo questo sul manuale, e nel primo esempio i valori sono definiti direttamente. Devo definirli al di fuori di QUALSIASI funzione per essere disponibile direttamente usando $GLOBALS['value'];?
Jack Johansson

2
Freddo. felice di averlo ottenuto. Nel primo esempio di questi documenti, le variabili sono dichiarate al di fuori di una funzione e nell'ambito globale. Pertanto, non globalè necessaria alcuna parola chiave. Nei nostri esempi, abbiamo lavorato nell'ambito delle funzioni, quindi la globalparola chiave è necessaria.
Dave Romsey,

1
I filtri sono nostri amici! :-) Sono sicuro che alcuni entusiasti risponditori saranno in giro per rispondere alle tue domande se hai bisogno di più aiuto!
Dave Romsey,

7

Ecco alcune soluzioni alternative:

Approccio n. 1

È possibile racchiudere la definizione dello shortcode e il posts_wherecallback del filtro in una classe per poter passare un determinato valore tra i metodi della classe, ad esempio come una variabile privata .

Approccio n. 2

Un altro approccio sarebbe passare il valore come input WP_Queryall'interno del callback del tuo shortcode:

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

e poi nel tuo filtro posts_where puoi accedervi:

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

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

    return $where;

}, 10, 2 );

Approccio n. 3

... oppure potresti anche regolare l' esempio di @the_dramatist per poter successivamente rimuovere il callback assegnando la funzione anonima a una variabile:

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

Controlla ad esempio i documenti PHP su come assegnare una funzione anonima, con la parola chiave use, a una variabile.

ps: Penso di aver appreso per la prima volta questo trucco di assegnazione di variabili da @gmazzap, per facilitare la rimozione del callback di un filtro anonimo.

Spero che sia d'aiuto!


Grazie birgire, risposta gentile e precisa come sempre. Mi consiglia di definire una funzione all'interno di una funzione piuttosto che utilizzare una variabile unica globale? Se sì, potresti dirmi perché?
Jack Johansson

Non sarebbe una buona idea, se avessimo bisogno di riutilizzare quella funzione ed è bloccata nell'ambito di un'altra funzione e sarebbe più difficile per altri sviluppatori, ad esempio, saltare il filtro con callback anonimi. Quindi, come plug-in formale per il repository wp.org, molto probabilmente proverei a consentire ad altri sviluppatori di rimuovere i filtri nel modo più semplice possibile ;-) In generale, proverei anche ad evitare di aggiungere più globali, poiché potrebbero esserci vari problemi approccio. Se entriamo in un angolo con la nostra struttura di plugin, allora forse è un segno usare una struttura alternativa, qualunque essa sia ;-)
birgire

Immagino che andrò con il tuo terzo approccio. Sembra funzionare nel mio caso. Saluti!
Jack Johansson

sicuramente qualunque cosa funzioni meglio per te. Potrei andare con # 1 o # 2 senza alcuna funzione anomala per rimuoverlo facilmente ;-) @JackJohansson
birgire

2
Possiamo effettivamente passare argomenti personalizzati e i loro valori per WP_Queryindirizzare una determinata istanza e accedervi attraverso vari filtri come posts_where, pre_get_postse posts_clauses. Questo è ciò che facciamo nell'approccio n. 2.
birgire,

4

Puoi usare la useparola chiave di PHP . Quindi, con l'aiuto di questa useparola chiave, puoi inserire una variabile all'interno di una funzione. E puoi anche scrivere una funzione anonima per ridurre il codice. Quindi tutto sarà-

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

Spero che aiuti.


È bello, ma le funzioni anonime sono difficili da sganciare.
Dave Romsey,

2
Ooh, la rimozione della funzione anonima è stata ora trattata da @birgire in un'altra risposta alla domanda. Freddo!
Dave Romsey,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.