¿Cómo obtener los valores de entrada de shortcode dentro de un filtro?


9

Estoy tratando de obtener el valor de entrada de un shortcode dentro de una función utilizada por un filtro, pero parece que no hay éxito. Aquí esta lo que hice:

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

Ahora sé que usar el $valueinterior filter_value()no funcionará debido a los ámbitos variables, pero incluso el uso $GLOBALS['value']no funciona.

Incluso intenté usarlo $value = $atts['id']dentro filter_value();pero tampoco tuve éxito.

¿Cómo puedo usar mi shortcode como [my-shortcode id='123']y pasar el valor 123 al filtro?

Gracias.

Respuestas:


7

Usar una variable global funcionará. Aquí hay una demostración:

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 al margen , declarar una función dentro de otra función no es una buena práctica .


Esto es realmente extraño. Si configuro el valor usando $GLOBALS['value'] = some valuey luego lo llamo $GLOBALS['value'], funciona, pero si configuro el valor directamente como $value = some valuey luego lo llamo usando $GLOBALS['value'], no funciona, aunque debería funcionar de acuerdo con el manual de PHP.
Jack Johansson

Debe establecer $valueel ámbito global con global $value;antes de inicializarlo con un valor. Por ejemplo, global $value; $value = $a['id']; en el filtro puedes hacer global $value; echo $value;¿Eso ayuda?
Dave Romsey

Si gracias. Estaba leyendo esto en el manual, y en el primer ejemplo los valores se definen directamente. ¿Tengo que definirlos fuera de CUALQUIER función para estar disponible directamente usando $GLOBALS['value'];?
Jack Johansson

2
Frio. Me alegro de que lo hayamos conseguido. En el primer ejemplo de esos documentos, las variables se declaran fuera de una función y dentro del alcance global. Por lo tanto, no globalse necesita una palabra clave. En nuestros ejemplos, hemos estado trabajando desde el alcance de las funciones, por lo que la globalpalabra clave es necesaria.
Dave Romsey

1
¡Los filtros son nuestros amigos! :-) Estoy seguro de que algunos ansiosos responderán para responder sus preguntas si necesita más ayuda.
Dave Romsey

7

Aquí hay algunas soluciones:

Enfoque n. ° 1

Puede ajustar la definición del shortcode y la posts_wheredevolución de llamada del filtro en una clase para poder pasar un valor dado entre los métodos de la clase, por ejemplo, como una variable privada .

Enfoque n. ° 2

Otro enfoque sería pasar el valor como entrada WP_Querydentro de la devolución de llamada de su shortcode:

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

y luego dentro del filtro posts_where puedes acceder a él:

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

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

    return $where;

}, 10, 2 );

Enfoque n. ° 3

... o también puede ajustar el ejemplo de @the_dramatist para poder eliminar la devolución de llamada luego asignando la función anónima a una 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' );   

Compruebe, por ejemplo, los documentos PHP sobre cómo asignar una función anónima, con la palabra clave use, a una variable.

ps: creo que aprendí por primera vez sobre este truco de asignación de variables de @gmazzap, para que sea más fácil eliminar la devolución de llamada de un filtro anónimo.

¡Espero eso ayude!


Gracias birgire, amable y precisa respuesta como siempre. ¿Recomienda definir una función dentro de una función sobre el uso de una variable única global? En caso afirmativo, ¿podría decirme por qué?
Jack Johansson

Esa no sería una buena idea, si necesitamos reutilizar esa función y está atascada dentro del alcance de otra función y sería más difícil para otros desarrolladores, por ejemplo, omitir el filtro con devoluciones de llamadas anónimas. Entonces, como un complemento formal para el repositorio de wp.org, probablemente trataría de permitir que otros desarrolladores eliminen los filtros lo más fácil posible ;-) También trataría en general de evitar agregar más globales, ya que puede haber varios problemas con eso Acercarse. Si nos metemos en una esquina con nuestra estructura de plugin, entonces tal vez es un signo de utilizar una estructura alternativa, sea lo que sea ;-)
birgire

Creo que voy con tu tercer enfoque. Parece funcionar en mi caso. ¡Salud!
Jack Johansson

seguro de lo que sea mejor para ti. Podría ir con el # 1 o # 2 sin una función cualquiera para eliminarlo fácilmente nuevamente ;-) @JackJohansson
birgire

2
De hecho, podemos transmitir argumentos personalizados y sus valores para WP_Queryapuntar a una instancia determinada y acceder a ella a través de varios filtros como posts_where, pre_get_postsy posts_clauses. Eso es lo que hacemos en el enfoque # 2.
Birgire

4

Puede usar la usepalabra clave de PHP . Entonces, con la ayuda de esta usepalabra clave, puede traer variables dentro de una función. Y también puede escribir una función anónima para reducir el código. Entonces todo 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 ayude.


Esto es genial, pero las funciones anónimas son difíciles de desenganchar.
Dave Romsey

2
Ooh, eliminar la función anónima ahora ha sido cubierto por @birgire en otra respuesta a la pregunta. ¡Frio!
Dave Romsey

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.