Як отримати вхідні значення короткого коду всередині фільтра?


9

Я намагаюся отримати вхідне значення короткого коду всередині функції, яка використовується фільтром, але, здається, немає успіху. Ось що я зробив:

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

Тепер я знаю, що використання $valueвсередині filter_value()не буде працювати через змінні області, але навіть використання $GLOBALS['value']не працює.

Я навіть намагався використовувати $value = $atts['id']всередині, filter_value();але успіху теж не було.

Як я можу використовувати свій короткий код, як [my-shortcode id='123']і передати значення 123 фільтру?

Дякую.

Відповіді:


7

Використання глобальної змінної спрацює. Ось демонстрація:

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

Бічна примітка, декларування функції в межах іншої функції не є хорошою практикою .


Це насправді дивно. Якщо я встановив значення за допомогою, $GLOBALS['value'] = some valueа потім зателефонував $GLOBALS['value']йому, воно працює, але якщо я встановити це значення безпосередньо як, $value = some valueа потім викликати його за допомогою, $GLOBALS['value']воно не працює, тоді як воно повинно працювати відповідно до посібника PHP.
Джек Йоханссон

Ви повинні встановити $valueглобальний діапазон, global $value;перш ніж ініціалізувати його зі значенням. Наприклад, global $value; $value = $a['id']; у фільтрі ви можете це зробити? global $value; echo $value;Чи це допомагає?
Дейв Ромсі

Так дякую. Я читав це в посібнику, і в першому прикладі значення визначаються безпосередньо. Чи потрібно мені визначати їх поза будь-якою функцією, щоб бути доступними безпосередньо за допомогою $GLOBALS['value'];?
Джек Йоханссон

2
Класно. рада, що ми його отримали. У першому прикладі цих документів змінні оголошуються поза функцією та в межах глобальної сфери. Отже, globalключове слово не потрібне. У наших прикладах ми працювали в межах функцій, тому globalключове слово є необхідним.
Дейв Ромсі

1
Фільтри - це наші друзі! :-) Я впевнений, що деякі охочі відповідуть на ваші запитання, якщо вам потрібна додаткова допомога!
Дейв Ромсі

7

Ось кілька вирішень:

Підхід №1

Ви можете зафіксувати визначення короткого коду та posts_whereзворотний виклик фільтра в класі, щоб мати змогу передавати задане значення між методами класу, наприклад, як приватна змінна.

Підхід №2

Іншим підходом буде передача значення як вхідного сигналу в WP_Queryмежах зворотного дзвінка вашого короткого коду:

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

а потім у вашому фільтрі posts_where ви можете отримати доступ до нього:

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

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

    return $where;

}, 10, 2 );

Підхід №3

... або ви також можете налаштувати приклад за допомогою @the_dramatist, щоб потім змогли видалити зворотний виклик, призначивши анонімну функцію змінній:

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

Наприклад, перевірте документи PHP про те, як призначити анонімну функцію за допомогою ключового слова use змінній.

ps: Я думаю, що я вперше дізнався про цю хитрість присвоєння трюку від @gmazzap, щоб полегшити видалення зворотного виклику анонімного фільтра.

Сподіваюся, це допомагає!


Дякую, як завжди, добру та точну відповідь. Чи рекомендуєте ви визначати функцію всередині функції над використанням глобальної унікальної змінної? Якщо так, ви можете, будь ласка, сказати мені, чому?
Джек Йоханссон

Це не було б гарною ідеєю, якщо нам потрібно повторно використовувати цю функцію, і вона застрягла в межах іншої функції, а іншим розробникам було б складніше, наприклад, пропустити фільтр з анонімними зворотними дзвінками. Отже, як офіційний плагін для репортажу wp.org я, швидше за все, намагаюся дозволити іншим розробникам видалити фільтри якомога простіше ;-) Я б також взагалі намагався уникати додавання більше глобальних даних, оскільки з цим можуть виникнути різні проблеми підхід. Якщо ми потрапимо в кут із нашою структурою плагінів, то, можливо, це знак використовувати альтернативну структуру, якою б це не було ;-)
birgire

Я думаю, я йду з твоїм третім підходом. Здається, у моєму випадку працює. Ура!
Джек Йоханссон

впевнений, що найкраще працює для вас. Я можу піти з №1 або №2 без будь-якої функції, щоб легко знову її зняти ;-) @JackJohansson
birgire

2
Фактично ми можемо передати призначені для користувача аргументи і їх значення для WP_Queryцільової даного екземпляра і доступ до нього через різні фільтри , такі як posts_where, pre_get_postsі posts_clauses. Це ми робимо підходом №2.
birgire

4

Ви можете використовувати useключове слово PHP . Тож за допомогою цього useключового слова ви можете ввести змінну всередині функції. А також ви можете написати анонімну функцію для зменшення коду. Отже вся справа буде-

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

Сподіваюся, що це допомагає.


Це круто, але анонімні функції важко відкрутити.
Дейв Ромсі

2
О, видалення анонімної функції тепер висвітлено в @birgire в іншій відповіді на питання. Класно!
Дейв Ромсі

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.