Como obter os valores de entrada do shortcode dentro de um filtro?


9

Estou tentando obter o valor de entrada de um código de acesso dentro de uma função usada por um filtro, mas parece não haver sucesso. Aqui está o que eu fiz:

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

Agora eu sei que usar $valuedentro filter_value()não funcionará por causa de escopos variáveis, mas mesmo usando $GLOBALS['value']não funciona.

Eu até tentei usar $value = $atts['id']dentro do, filter_value();mas sem sucesso também.

Como posso usar o meu shortcode como [my-shortcode id='123']e passar o valor 123 para o filtro?

Obrigado.

Respostas:


7

Usar uma variável global funcionará. Aqui está uma demonstração:

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 lateral, declarar uma função dentro de outra função não é uma boa prática .


Isso é realmente estranho. Se eu definir o valor usando $GLOBALS['value'] = some valuee depois chamá- $GLOBALS['value']lo, ele funciona, mas se eu definir o valor diretamente como $value = some valuee depois chamá-lo usando, $GLOBALS['value']ele não funcionará, embora deva funcionar de acordo com o manual do PHP.
Jack Johansson

Você deve definir $valueo escopo global global $value;antes de inicializá-lo com um valor. Por exemplo, global $value; $value = $a['id']; no filtro, você pode fazer global $value; echo $value;Isso ajuda?
Dave Romsey

Sim obrigado. Eu estava lendo isso no manual e, no primeiro exemplo, os valores são definidos diretamente. Preciso defini-los fora de QUALQUER função para estar disponível diretamente usando $GLOBALS['value'];?
Jack Johansson

2
Legal. feliz que conseguimos. No primeiro exemplo desses documentos, as variáveis ​​são declaradas fora de uma função e dentro do escopo global. Portanto, nenhuma globalpalavra-chave é necessária. Em nossos exemplos, trabalhamos no escopo de funções, portanto a globalpalavra-chave é necessária.
Dave Romsey

11
Os filtros são nossos amigos! :-) Tenho certeza que alguns atendentes ansiosos estarão por perto para responder às suas perguntas, se você precisar de mais ajuda!
Dave Romsey

7

Aqui estão algumas soluções alternativas:

Abordagem # 1

Você pode agrupar a definição do código de acesso e o posts_whereretorno de chamada do filtro em uma classe para poder transmitir um determinado valor entre os métodos da classe, por exemplo, como uma variável privada .

Abordagem # 2

Outra abordagem seria passar o valor como uma entrada para WP_Queryo retorno de chamada do seu código curto:

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

e, no filtro posts_where, você pode acessá-lo:

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

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

    return $where;

}, 10, 2 );

Abordagem # 3

... ou você também pode ajustar o exemplo por @the_dramatist para poder remover o retorno de chamada posteriormente, atribuindo a função anônima a uma variável:

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

Verifique, por exemplo, a documentação do PHP sobre como atribuir uma função anônima, com a palavra-chave use, a uma variável.

ps: Acho que aprendi sobre esse truque de atribuição de variáveis ​​pelo @gmazzap, para facilitar a remoção de retorno de chamada de um filtro anônimo.

Espero que ajude!


Obrigado birgire, resposta amável e precisa, como sempre. Você recomenda definir uma função dentro de uma função usando uma variável exclusiva global? Se sim, você poderia me dizer por quê?
Jack Johansson

Isso não seria uma boa idéia, se precisarmos reutilizar essa função e ela estiver presa no escopo de outra função e seria mais difícil para outros desenvolvedores, por exemplo, pular o filtro com retornos de chamada anônimos. Portanto, como um plugin formal para o repositório wp.org, provavelmente tentarei permitir que outros desenvolvedores removam os filtros o mais fácil possível ;-) Em geral, também tentaria evitar adicionar mais globais, pois pode haver vários problemas com isso. aproximação. Se entrar em um canto com nossa estrutura de plugin, então talvez seja um sinal de utilizar uma estrutura alternativa, qualquer que seja ;-)
birgire

Acho que vou com a sua terceira abordagem. Parece funcionar no meu caso. Felicidades!
Jack Johansson

Certifique-se de que funciona melhor para você. Eu poderia ir com # 1 ou # 2 sem função anyomous facilmente removê-lo novamente ;-) @JackJohansson
birgire

2
Na verdade, podemos transmitir argumentos personalizados e seus valores para WP_Querydirecionar uma determinada instância e acessá-la através de vários filtros como posts_where, pre_get_postse posts_clauses. É o que fazemos na abordagem nº 2.
Birgire

4

Você pode usar a usepalavra - chave PHP . Portanto, com a ajuda dessa usepalavra - chave, você pode trazer variáveis ​​para dentro de uma função. E também você pode escrever uma função anônima para reduzir o código. Então a coisa toda será-

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

Espero que ajude.


Isso é legal, mas é difícil desvincular funções anônimas.
Dave Romsey

2
Ooh, a remoção da função anônima agora foi abordada pelo @birgire em outra resposta à pergunta. Legal!
Dave Romsey

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.