如何将外部变量传递给过滤器/操作


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


只需在该函数中进行“疯狂的计算” ...
onetrickpony 2012年

从我的简化示例中可能很难理解。$ score变量在整个模板中使用。我只想计算一次,然后将该值传递给函数,该函数是用于更改页面标题的过滤器的回调。此过滤器用于“多合一SEO包”中。不需要多次运行计算。
kingkool68

然后,如果要获得不涉及引入全局状态(永远不需要)的解决方案,则应该发布更多代码。
onetrickpony 2012年

这是模板文件中的完整代码。$score通过遍历事物数组并增加变量来计算。 pastebin.com/fkSXY04m
kingkool68'4

Answers:


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 2012年

1
全球是邪恶的 ”?真的吗 然后最好编写整个WordPress代码,因为它依赖于许多全局变量
Chip Bennett

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

3
匿名函数不应在add_filter()add_action()调用中使用。无法通过删除它们remove_function()
Chip Bennett

您的意思是remove_filter,主要用于删除内置过滤器,而不是由插件/主题添加的过滤器...
onetrickpony 2012年

1
是; 抱歉:remove_filter()remove_action()。而且也没有理由插件/主题过滤器应该不能合理地能够被删除:覆盖插件样式入队,儿童主题,等等
芯片贝内特

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 2012年

再一次声明“全局”。看他的第二个例子,他两次声明了gloabl $ wp!
亚当

它也不起作用。这是我尝试的第一件事。
kingkool68

在传递给过滤器之前,您是否能够printecho确保结果确实能够正常工作?
亚当

糟糕!全球化$score确实有效。我先搞砸了,$score然后设置全球化,这显然是行不通的。$score首先进行全球化,然后赋予其价值,以正确的方式进行工作符合预期。谢谢大家
kingkool68
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.