Como passar variáveis ​​externas para filtros / ações

11

Acho que preciso passar dados personalizados para um filtro fornecido por um plug-in de terceiros. Todas as maneiras pelas quais eu vi isso são realmente complicadas e difíceis de entender.

Veja este exemplo:

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

Como posso passar a $scorevariável add_score_to_title()?

O que acabei fazendo foi adicionar minha variável ao $wpobjeto global . Então você acaba com isso:

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

Sujo? Talvez. Simples? Sim! Alguma desvantagem dessa técnica? Por favor, discuta.

ATUALIZAÇÃO Aqui está o código completo em questão -> http://pastebin.com/fkSXY04m

kingkool68
fonte
Basta fazer o seu "cálculo louco" dentro daquela função ...
onetrickpony
Provavelmente é difícil entender do meu exemplo simplificado. A variável $ score é usada em todo esse modelo. Quero calcular uma vez e passar esse valor para a função que é um retorno de chamada para um filtro para alterar o título da página. Esse filtro é usado no All In One SEO Pack. A execução do cálculo várias vezes não é desejada.
kingkool68
Em seguida, você deve postar mais código se desejar obter uma solução que não envolva a introdução de um estado global (o que nunca deve ser necessário).
Onetrickpony
Aqui está o código completo em um arquivo de modelo. $scoreé calculado fazendo um loop sobre uma matriz de coisas e incrementando uma variável. pastebin.com/fkSXY04m
kingkool68

Respostas:

10

Você tem pelo menos duas opções:

  1. Globalize a variável desejada e faça referência a ela dentro do retorno de chamada
  2. Embrulhe a lógica de cálculo da pontuação com uma função e faça referência a ela dentro do retorno de chamada

Globalize a variável

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

Finalizar o cálculo da pontuação

Se você precisar apenas do cálculo de pontuação dentro do filtro, insira a lógica no próprio retorno de chamada:

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

Melhor ainda, você pode agrupar seu cálculo de pontuação em uma função própria e depois chamar essa função dentro de seu retorno de chamada:

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

Se você encontrar problemas para referenciar o $_POSTobjeto, também poderá registrar sua variável de consulta e usar get_query_var()internamente para obter dados:

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

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

Com isso no lugar, $_POST['Q']pode ser substituído por get_query_var('Q').

Chip Bennett
fonte
Isto não tem nada a ver com o número de argumentos passados para a função por apply_filters ...
onetrickpony
Tentei o método nº 1 que você mencionou sobre globalizar a variável. Isso não funciona. O parâmetro args aceito também não me ajuda, pois não tenho controle sobre quais variáveis ​​são passadas para a função de retorno de chamada.
kingkool68
Desculpe, você estava certa. Eu calculei $scoreprimeiro e depois globalizei. Não é à toa que não estava funcionando. Obrigado!
precisa saber é o seguinte
-1. Primeira opção expõe uma variável no estado global, 2ª opção não funciona ...
onetrickpony
1
" Globais são maus "? Sério ? Então é melhor escrever todo o código do WordPress, uma vez que se baseia em várias variáveis ​​globais .
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;
}

Chame a função em qualquer lugar do seu script para obter a pontuação, ela será calculada apenas uma vez.

Outra maneira, usando funções anônimas :

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

add_filter('aioseop_title_single', function($title) use($score){
  return 'Quiz Results (' . $score . ') - ' . $title;  
});
onetrickpony
fonte
3
Funções anônimas não devem ser usadas add_filter()ou add_action()chamadas. Eles não podem ser removidos via remove_function().
Chip Bennett
Você remove_filter média, que é usado principalmente para remover built-in filtros, não os filtros adicionados por plugins / temas ...
onetrickpony
1
Sim; desculpe: remove_filter()e remove_action(). E não há nenhuma razão que os filtros Plugin / temáticos não devem razoavelmente ser capaz de ser removido: override Plugin enfileira folha de estilo, Temas de crianças, etc.
Chip Bennett
0

O exemplo a seguir vê a variável $my_calculationno escopo global, no entanto, de dentro da nossa função local, precisamos declarar global $my_calculationpara acessar a variável no escopo global.

<?php 

    $my_calculation = 'result!';

    function my_function() {

        global $my_calculation;
        return $my_calculation;

    }

    add_filter( 'function_something_here', 'my_function');   

?>

Esta é apenas uma maneira de fazê-lo e parece estar limpo. Isso funcionaria para você?

Adão
fonte
Como isso é diferente do que ele já tem?
Onetrickpony
Mais uma vez declaração de "global". Veja o seu segundo exemplo, ele declara gloabl $ wp duas vezes!
11114 Adam
Também não funciona. Esta é a primeira coisa que tentei.
precisa saber é o seguinte
Você é capaz printou echoseu resultado para garantir que sua função esteja realmente funcionando antes de passá-la para o filtro?
Adam
Opa! Globalizar $scorerealmente funciona. Eu brinquei e comecei a $scoreglobalizar, o que claramente não funciona. Fazer da maneira correta, globalizando $scoreprimeiro e depois atribuindo um valor, funciona conforme o esperado. Obrigado a todos.
precisa saber é o seguinte