Comment passer des variables externes aux filtres / actions

11

Je me retrouve à devoir transmettre des données personnalisées à un filtre fourni par un plugin tiers. Toutes les façons dont j'ai vu cela sont vraiment compliquées et difficiles à comprendre.

Prenez cet exemple:

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

Comment passer la $scorevariable à add_score_to_title()?

J'ai fini par ajouter ma variable à l' $wpobjet global . Vous vous retrouvez donc avec ceci:

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

Sale? Peut être. Facile? Ouaip! Des inconvénients à cette technique? Débattez s'il vous plaît.

MISE À JOUR Voici le code complet en question -> http://pastebin.com/fkSXY04m

kingkool68
la source
Faites simplement votre "calcul fou" à l'intérieur de cette fonction ...
onetrickpony
C'est probablement difficile à comprendre à partir de mon exemple simplifié. La variable $ score est utilisée dans ce modèle. Je veux le calculer une fois et passer cette valeur à la fonction qui est un rappel pour un filtre pour changer le titre de la page. Ce filtre est utilisé dans le pack SEO All In One. Il n'est pas souhaitable d'exécuter le calcul plusieurs fois.
kingkool68
Ensuite, vous devez publier plus de code si vous souhaitez obtenir une solution qui n'implique pas l'introduction d'un état global (qui ne devrait jamais être nécessaire).
onetrickpony le
Voici le code complet dans un fichier modèle. $scoreest calculé en bouclant sur un tableau de choses et en incrémentant une variable. pastebin.com/fkSXY04m
kingkool68

Réponses:

10

Vous avez au moins deux options:

  1. Globalisez la variable souhaitée, puis référencez-la dans le rappel
  2. Enveloppez la logique de calcul du score avec une fonction, puis référencez-la dans le rappel

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

Envelopper le calcul du score

Si vous n'avez besoin que du calcul du score à l' intérieur du filtre, insérez la logique dans le rappel lui-même:

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

Mieux encore, vous pouvez encapsuler votre calcul de score dans une fonction qui lui est propre, puis appeler cette fonction dans votre rappel:

<?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 vous trouvez que vous rencontrez des problèmes pour référencer l' $_POSTobjet, vous pouvez également enregistrer votre variable de requête, puis l'utiliser en get_query_var()interne pour obtenir des données:

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

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

Avec cela en place, $_POST['Q']peut être remplacé par get_query_var('Q').

Chip Bennett
la source
Cela n'a rien à voir avec le nombre d'arguments passés à la fonction par apply_filters ...
onetrickpony
Méthode éprouvée n ° 1 que vous mentionnez de la mondialisation de la variable. Ça ne marche pas. Le paramètre args accepté ne m'aide pas non plus, car je n'ai aucun contrôle sur les variables transmises à la fonction de rappel.
kingkool68
Désolé tu avais raison. J'ai d' $scoreabord calculé puis mondialisé. Pas étonnant que cela ne fonctionne pas. Je vous remercie!
kingkool68
-1. La première option expose une variable à l'état global, la deuxième option ne fonctionne pas ...
onetrickpony
1
"Les globaux sont mauvais "? Vraiment ? Ensuite, le code WordPress entier devrait être écrit, car il repose sur un certain nombre de 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;
}

Appelez la fonction n'importe où dans votre script pour obtenir le score, il ne sera calculé qu'une seule fois.

Une autre façon, en utilisant des fonctions anonymes :

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

add_filter('aioseop_title_single', function($title) use($score){
  return 'Quiz Results (' . $score . ') - ' . $title;  
});
onetrickpony
la source
3
Les fonctions anonymes ne doivent pas être utilisées dans add_filter()ou les add_action()appels. Ils ne peuvent pas être supprimés via remove_function().
Chip Bennett
Vous voulez dire remove_filter, qui est principalement utilisé pour supprimer les filtres intégrés, pas les filtres ajoutés par les plugins / thèmes ...
onetrickpony
1
Oui; désolé: remove_filter()et remove_action(). Et il n'y a aucune raison pour que les filtres de plugin / thème ne puissent raisonnablement pas être supprimés: remplacer les files d'attente de feuilles de style de plugin, les thèmes enfants, etc.
Chip Bennett
0

L'exemple suivant voit la variable $my_calculationdans la portée globale, mais à partir de notre fonction locale, nous devons déclarer global $my_calculationafin d'accéder à la variable dans la portée globale.

<?php 

    $my_calculation = 'result!';

    function my_function() {

        global $my_calculation;
        return $my_calculation;

    }

    add_filter( 'function_something_here', 'my_function');   

?>

Ce n'est qu'une façon de procéder et cela semble être net. Est-ce que cela fonctionnerait pour vous?

Adam
la source
En quoi est-ce différent de ce qu'il a déjà?
onetrickpony le
Une fois de moins déclaration de "global". Regardez son deuxième exemple, il déclare gloabl $ wp deux fois!
Adam
Cela ne fonctionne pas non plus. C'est la première chose que j'ai essayée.
kingkool68
Pouvez-vous printou echovotre résultat vous assurer que votre fonction fonctionne bien avant de la passer au filtre?
Adam
Oops! La mondialisation $scorefonctionne effectivement. J'ai gaffé et mis en $scorepremier puis mondialisé, ce qui ne fonctionne clairement pas. Le faire correctement en globalisant d' $scoreabord puis en lui donnant une valeur fonctionne comme prévu. Merci a tous.
kingkool68