Как передать внешние переменные в фильтры / действия

11

Мне нужно передать пользовательские данные в фильтр, предоставленный сторонним плагином. Все способы, которые я видел, чтобы сделать это, действительно сложны и трудно обернуть мою голову вокруг.

Возьмите этот пример:

$score = 42; //Some crazy calculation I don't want to repeat.

function add_score_to_title($title) {
    return 'Quiz Results (' . $score . '/') - ' . $title;
}

add_filter( 'aioseop_title_single', 'add_score_to_title');

Как я могу передать $scoreпеременную add_score_to_title()?

В итоге я добавил свою переменную в глобальный $wpобъект. Итак, вы в конечном итоге с этим:

global $wp;
$score = 42; //Some crazy calculation I don't want to repeat.
$wp->some_random_name_for_score = $score;

function add_score_to_title($title) {
    global $wp;
    $score = $wp->some_random_name_for_score;
    return 'Quiz Results (' . $score . '/') - ' . $title;
}

add_filter( 'aioseop_title_single', 'add_score_to_title');

Грязные? Может быть. Просто? Ага! Есть ли недостатки этой техники? Пожалуйста, обсудите.

ОБНОВЛЕНИЕ Вот полный рассматриваемый код -> http://pastebin.com/fkSXY04m

kingkool68
источник
Просто сделайте свой "сумасшедший расчет" внутри этой функции ...
onetrickpony
Это, вероятно, трудно понять из моего упрощенного примера. Переменная $ score используется во всем этом шаблоне. Я хочу вычислить его один раз и передать это значение функции, которая является обратным вызовом для фильтра для изменения заголовка страницы. Этот фильтр используется в пакете SEO «все в одном». Запускать вычисления несколько раз нежелательно.
kingkool68
Затем вы должны опубликовать больше кода, если вы хотите получить решение, которое не предполагает введения глобального состояния (которое никогда не требуется).
onetrickpony
Вот полный код в файле шаблона. $scoreрассчитывается путем зацикливания на массиве вещей и увеличения переменной. pastebin.com/fkSXY04m
kingkool68

Ответы:

10

У вас есть как минимум два варианта:

  1. Глобализировать желаемую переменную, а затем ссылаться на нее внутри обратного вызова
  2. Оберните логику вычисления оценки функцией, а затем сделайте ссылку на нее внутри обратного вызова

Глобализировать переменную

<?php
global $score;
$score = 42; //Some crazy calculation I don't want to repeat.

function add_score_to_title($title) {
    global $score;
    return 'Quiz Results (' . $score . '/') - ' . $title;
}

add_filter( 'aioseop_title_single', 'add_score_to_title');
?>

Оберните расчет баллов

Если вам когда-либо понадобится вычисление оценки внутри фильтра, включите логику в сам обратный вызов:

<?php
function add_score_to_title($title) {
    $score = 0;
    $questions = get_quiz_result_questions();
    $total_questions = 0;
    foreach( $questions as $question ) {
        $order = $question->order;

        if( $order >= 100 ) {
            break;
    }

    if( $question->correct == $_POST['Q'][$order] ) {
        $score++;
    }
    $total_questions++;

    return 'Quiz Results (' . $score . '/') - ' . $title;
}

add_filter( 'aioseop_title_single', 'add_score_to_title');
?>

А еще лучше, вы можете обернуть вычисление баллов в собственную функцию, а затем вызвать эту функцию внутри вашего обратного вызова:

<?php
function wpse48677_get_score() {
    $score = 0;
    $questions = get_quiz_result_questions();
    $total_questions = 0;
    foreach( $questions as $question ) {
    $order = $question->order;

    if( $order >= 100 ) {
        break;
    }

    if( $question->correct == $_POST['Q'][$order] ) {
        $score++;
    }
    $total_questions++;
    $output['score'] = $score;
    $output['total_questions'] = $total_questions;

    return $output;
}

function add_score_to_title($title) {

    $score_results = wpse48677_get_score();

    $score = $score_results['score'];

    return 'Quiz Results (' . $score . '/') - ' . $title;
}

add_filter( 'aioseop_title_single', 'add_score_to_title');
?>

Если вы обнаружите, что у вас есть проблемы со ссылкой на $_POSTобъект, вы можете также зарегистрировать переменную запроса и затем использовать ее get_query_var()для получения данных:

function add_score_query_vars( $query_vars ) {
    $query_vars[] = 'Q';

    return $query_vars;
}
add_filter( 'query_vars', 'add_score_query_vars' );

С этим на месте, $_POST['Q']можно заменить на get_query_var('Q').

Чип Беннетт
источник
Это не имеет никакого отношения к числу аргументов, передаваемых функции apply_filters ...
onetrickpony
Попробованный метод № 1 вы упомянули о глобализации переменной. Не работает Принятый параметр args мне тоже не помогает, так как я не контролирую, какие переменные передаются в функцию обратного вызова.
kingkool68
Извините, вы были правы. $scoreСначала я вычислил, а затем глобализировал его. Не удивительно, что это не сработало. Спасибо!
kingkool68
-1. Первый вариант выставляет переменную в глобальном состоянии, второй вариант не работает ...
onetrickpony
1
" Глобалы злые "? Действительно ? Тогда лучше написать весь код WordPress, так как он использует довольно много глобальных переменных .
Чип Беннетт
3
function add_score_to_title($title = false) {
  static $score = false;

  if($score === false){
    // do calc
  }

  // plugin call (filter)   
  if($title !== false)
    return 'Quiz Results (' . $score . ') - ' . $title;

  // your call
  return $score;
}

Вызовите функцию в любом месте вашего скрипта, чтобы получить оценку, она будет рассчитана только один раз.

Другой способ, используя анонимные функции :

// do the calc
$score = 'xxx';

add_filter('aioseop_title_single', function($title) use($score){
  return 'Quiz Results (' . $score . ') - ' . $title;  
});
onetrickpony
источник
3
Не следует использовать анонимные функции add_filter()или add_action()вызовы. Они не могут быть удалены через remove_function().
Чип Беннетт
Вы имеете в виду remove_filter, который в основном используется для удаления встроенных фильтров, а не фильтров, добавляемых плагинами / темами ...
onetrickpony
1
Да; извините: remove_filter()и remove_action(). И нет никаких причин, по которым фильтры плагинов / тем не могут быть разумно удалены: переопределить очереди таблиц стилей плагинов, дочерние темы и т. Д.
Chip Bennett
0

В следующем примере переменная видится $my_calculationв глобальной области видимости, однако внутри нашей локальной функции мы должны объявить ее global $my_calculation, чтобы получить доступ к переменной в глобальной области видимости.

<?php 

    $my_calculation = 'result!';

    function my_function() {

        global $my_calculation;
        return $my_calculation;

    }

    add_filter( 'function_something_here', 'my_function');   

?>

Это всего лишь один из способов сделать это, и он кажется аккуратным. Будет ли это работать для вас?

Адам
источник
Чем это отличается от того, что он уже имеет?
onetrickpony
Еще раз декларация "глобальная". Посмотрите на его второй пример, он объявляет gloabl $ wp дважды!
Адам
Это также не работает. Это первое, что я попробовал.
kingkool68
Можете ли вы printили echoваш результат убедиться, что ваша функция действительно работает до ее передачи в фильтр?
Адам
К сожалению! Глобализация $scoreдействительно работает. Я обманываю и устанавливаю $scoreсначала глобализированный, который явно не работает. Правильное выполнение, $scoreсначала глобализация, а затем присвоение значения, работает, как и ожидалось. Спасибо всем.
kingkool68