Cómo pasar variables externas a filtros / acciones

11

Me encuentro necesitando pasar datos personalizados a un filtro proporcionado por un complemento de terceros. Todas las formas en que he visto hacer esto son realmente complicadas y difíciles de entender.

Toma este ejemplo:

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

¿Cómo puedo pasar la $scorevariable a add_score_to_title()?

Lo que terminé haciendo fue agregar mi variable al $wpobjeto global . Entonces terminas con esto:

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

¿Sucio? Tal vez. ¿Simple? ¡Sip! ¿Alguna desventaja de esta técnica? Por favor discutelo.

ACTUALIZACIÓN Aquí está el código completo en cuestión -> http://pastebin.com/fkSXY04m

kingkool68
fuente
Simplemente haga su "cálculo loco" dentro de esa función ...
onetrickpony
Probablemente sea difícil de entender a partir de mi ejemplo simplificado. La variable $ score se usa en toda esa plantilla. Quiero calcularlo una vez y pasar ese valor a la función, que es una devolución de llamada para un filtro para cambiar el título de la página. Este filtro se usa en el All In One SEO Pack. No se desea ejecutar el cálculo varias veces.
kingkool68
Luego, debe publicar más código si desea obtener una solución que no implique la introducción de un estado global (que nunca debería ser necesario).
onetrickpony
Aquí está el código completo en un archivo de plantilla. $scorese calcula recorriendo un conjunto de cosas e incrementando una variable. pastebin.com/fkSXY04m
kingkool68

Respuestas:

10

Tienes al menos dos opciones:

  1. Globalice la variable deseada y luego haga referencia a ella dentro de la devolución de llamada
  2. Envuelva la lógica de cálculo de puntaje con una función, luego haga referencia a ella dentro de la devolución de llamada

Globalizar la variable

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

Ajustar el cálculo del puntaje

Si solo necesita el cálculo de puntaje dentro del filtro, inserte la lógica en la devolución de llamada:

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

Mejor aún, podría ajustar su cálculo de puntaje en una función propia y luego llamar a esa función dentro de su devolución de llamada:

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

Si tiene problemas para hacer referencia al $_POSTobjeto, también puede registrar su variable de consulta y luego usarla get_query_var()internamente para obtener datos:

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

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

Con esto en su lugar, $_POST['Q']se puede reemplazar con get_query_var('Q').

Chip Bennett
fuente
Esto no tiene nada que ver con el número de argumentos pasados ​​a la función por apply_filters ...
onetrickpony
Intentó el método # 1 que menciona de globalizar la variable. No funciona El parámetro args aceptado tampoco me ayuda, ya que no tengo control sobre qué variables se pasan a la función de devolución de llamada.
kingkool68
Lo siento, tenías razón. Calculé $scoreprimero y luego lo globalicé. No es de extrañar que no funcionara. ¡Gracias!
kingkool68
-1. La primera opción expone una variable en el estado global, la segunda opción no funciona ...
onetrickpony
1
" Globals son malvados "? Enserio ? Entonces es mejor escribir todo el código de WordPress, ya que se basa en bastantes variables globales .
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;
}

Llame a la función en cualquier parte de su script para obtener la puntuación, solo se calculará una vez.

Otra forma, usando funciones anónimas :

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

add_filter('aioseop_title_single', function($title) use($score){
  return 'Quiz Results (' . $score . ') - ' . $title;  
});
Pony de un solo truco
fuente
3
No se deben utilizar funciones anónimas add_filter()ni add_action()llamadas. No se pueden eliminar a través de remove_function().
Chip Bennett
Te refieres a remove_filter, que se usa principalmente para eliminar filtros integrados, no filtros agregados por complementos / temas ...
onetrickpony
1
Si; lo siento: remove_filter()y remove_action(). Y no hay ninguna razón por la que los filtros de Complemento / Tema no puedan eliminarse razonablemente: anule las colas de la hoja de estilo del Complemento, Temas infantiles, etc.
Chip Bennett
0

El siguiente ejemplo ve la variable $my_calculationen el alcance global, sin embargo, desde nuestra función local, debemos declarar global $my_calculationpara acceder a la variable en el alcance global.

<?php 

    $my_calculation = 'result!';

    function my_function() {

        global $my_calculation;
        return $my_calculation;

    }

    add_filter( 'function_something_here', 'my_function');   

?>

Esta es solo una forma de hacerlo y parece estar ordenada. Que este trabajo para usted?

Adán
fuente
¿Cómo es esto diferente de lo que ya tiene?
onetrickpony
Una vez menos declaración de "global". Mira su segundo ejemplo, ¡declara gloabl $ wp dos veces!
Adam
Tampoco funciona. Esto es lo primero que probé.
kingkool68
¿Puede usted printo echosu resultado asegurarse de que su función esté funcionando antes de pasarla al filtro?
Adam
¡Uy! La globalización $scoresí funciona. Me burlé y establecí $scoreprimero luego globalizado, lo que claramente no funciona. Hacerlo de la manera adecuada al globalizar $scoreprimero y luego darle un valor funciona como se esperaba. Gracias a todos.
kingkool68