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.