Come Passare Variabili Esterne a Filtri/Azioni

11 apr 2012, 22:37:25
Visualizzazioni: 25.3K
Voti: 12

Mi trovo nella necessità di passare dati personalizzati a un filtro fornito da un plugin di terze parti. Tutti i modi che ho visto per farlo sono davvero complicati e difficili da comprendere.

Prendi questo esempio:

$score = 42; //Un calcolo complesso che non voglio ripetere.

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

add_filter( 'aioseop_title_single', 'add_score_to_title');

Come posso passare la variabile $score alla funzione add_score_to_title()?

Quello che ho finito per fare è stato aggiungere la mia variabile all'oggetto globale $wp. Quindi si ottiene questo:

global $wp;
$score = 42; //Un calcolo complesso che non voglio ripetere.
$wp->some_random_name_for_score = $score;

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

add_filter( 'aioseop_title_single', 'add_score_to_title');

Sporco? Forse. Semplice? Sì! Ci sono svantaggi in questa tecnica? Vi prego di discuterne.

AGGIORNAMENTO Ecco il codice completo in questione -> http://pastebin.com/fkSXY04m

5
Commenti

Semplicemente esegui il tuo "calcolo pazzo" all'interno di quella funzione...

onetrickpony onetrickpony
11 apr 2012 22:45:42

Probabilmente è difficile da capire dal mio esempio semplificato. La variabile $score viene utilizzata in tutto quel template. Voglio calcolarla una volta e passare quel valore alla funzione che è un callback per un filtro che modifica il titolo della pagina. Questo filtro viene utilizzato in All In One SEO Pack. Eseguire il calcolo più volte non è desiderabile.

kingkool68 kingkool68
11 apr 2012 22:54:33

Allora dovresti postare più codice se vuoi ottenere una soluzione che non implichi l'introduzione di stati globali (che non dovrebbero mai essere necessari).

onetrickpony onetrickpony
11 apr 2012 23:00:03

Ecco il codice completo in un file template. $score viene calcolato ciclando su un array di elementi e incrementando una variabile.

http://pastebin.com/fkSXY04m

kingkool68 kingkool68
11 apr 2012 23:07:43

possibile duplicato di Passaggio di un parametro a funzioni di filtro e azione

T.Todua T.Todua
14 mag 2015 12:20:32
Tutte le risposte alla domanda 3
14
12

Hai almeno due opzioni:

  1. Globalizzare la variabile desiderata e poi riferirsi ad essa all'interno del callback
  2. Includere la logica di calcolo del punteggio in una funzione, quindi riferirsi ad essa all'interno del callback

Globalizzare la Variabile

<?php
global $score;
$score = 42; //Un calcolo complesso che non voglio ripetere.

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

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

Includere il Calcolo del Punteggio

Se hai bisogno del calcolo del punteggio solo all'interno del filtro, puoi inserire la logica direttamente nel callback:

<?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 'Risultati Quiz (' . $score . '/') - ' . $title;
}

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

Ancora meglio, potresti racchiudere il calcolo del punteggio in una funzione separata e poi chiamarla all'interno del tuo callback:

<?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 'Risultati Quiz (' . $score . '/') - ' . $title;
}

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

Se hai problemi a referenziare l'oggetto $_POST, puoi anche registrare la tua variabile di query e poi usare get_query_var() internamente per ottenere i dati:

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

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

Con questo impostato, $_POST['Q'] può essere sostituito con get_query_var('Q').

11 apr 2012 22:44:34
Commenti

Questo non ha nulla a che fare con il numero di argomenti passati alla funzione da apply_filters...

onetrickpony onetrickpony
11 apr 2012 22:46:40

Ho provato il metodo #1 che hai menzionato di globalizzare la variabile. Non funziona. Il parametro accepted args non mi aiuta neanche poiché non ho controllo su quali variabili vengono passate alla funzione di callback.

kingkool68 kingkool68
11 apr 2012 22:55:58

Scusa avevi ragione. Ho calcolato prima $score e poi l'ho globalizzata. Non c'è da stupirsi che non funzionasse. Grazie!

kingkool68 kingkool68
11 apr 2012 23:11:35

-1. La prima opzione espone una variabile nello stato globale, la seconda opzione non funziona...

onetrickpony onetrickpony
11 apr 2012 23:28:23

Aggiornato per riflettere il mio errore sulla seconda opzione. Ma cosa c'è di male nell'esporre una variabile globale? È sicuramente meglio che usare una funzione anonima in un callback. :)

Chip Bennett Chip Bennett
11 apr 2012 23:29:57

No, non lo è. E qui ci sono alcune ragioni per cui dovresti evitare questa pratica. Forse va bene per il suo caso specifico, ma se qualcuno sviluppasse davvero un plugin pubblico usando la tua soluzione?

onetrickpony onetrickpony
11 apr 2012 23:34:10

"Le variabili globali sono il male"? Davvero? Allora tutto il codice di WordPress dovrebbe essere riscritto, visto che si basa su diverse variabili globali.

Chip Bennett Chip Bennett
11 apr 2012 23:37:14

Esatto. Questa è una delle ragioni per cui il codice base di WP è tra i peggiori sul web. Comunque, WP ha una scusa - la necessaria compatibilità con plugin progettati per versioni più vecchie. Tu non hai questo problema :)

onetrickpony onetrickpony
11 apr 2012 23:38:44

Sì... lascerò perdere questo punto. Grazie per aver segnalato il problema con la seconda opzione; l'ho rimossa dalla domanda. Mantengo la mia posizione sull'accettabilità dell'uso di variabili globali. Se sapessi come viene generato o restituito l'output del Plugin, potrei probabilmente offrire una soluzione migliore.

Chip Bennett Chip Bennett
11 apr 2012 23:44:32

Vedi la risposta aggiornata; dopo aver esaminato il Pastebin, ho proposto due metodi che preferirei invece di utilizzare una variabile globale.

Chip Bennett Chip Bennett
11 apr 2012 23:52:06

Meglio, ma vuole che il "punteggio" sia accessibile più avanti nello script, senza ricalcolarlo, quindi l'uso di una variabile "statica" ha senso in questo caso.

onetrickpony onetrickpony
11 apr 2012 23:57:55

Utilizzando una funzione per calcolare il punteggio: non si potrebbe memorizzare il calcolo nella cache degli oggetti?

Stephen Harris Stephen Harris
12 apr 2012 00:48:47

autunno 2015 e WP fa ancora affidamento su variabili globali dannose. La scusa è diventata troppo vecchia. E +1 per il suggerimento sulla globalizzazione. Nel mio caso la callback aveva bisogno di accedere a $user che ho dovuto globalizzare visto che la mia chiamata apply_filters veniva inizializzata all'interno di una funzione.

Ejaz Ejaz
7 ott 2015 20:56:50

Queste globali sono dannose, la gente deve rilassarsi. Mi piace molto questa risposta. L'OP ha chiesto come passare variabili tra funzioni. Questa risposta spiega diversi modi per farlo. Inizia con le globali, che è meglio evitare, ma rimangono una cosa che esiste e risolve il problema in questione. Poi la risposta procede spiegando diverse opzioni migliori che potrebbero funzionare in alcune circostanze.

squarecandy squarecandy
21 set 2017 18:25:43
Mostra i restanti 9 commenti
3
function add_score_to_title($title = false) {
  static $score = false;

  if($score === false){
    // esegui il calcolo
  }

  // chiamata del plugin (filtro)   
  if($title !== false)
    return 'Risultati del Quiz (' . $score . ') - ' . $title;

  // tua chiamata
  return $score;
}

Chiama la funzione in qualsiasi punto del tuo script per ottenere il punteggio, verrà calcolato solo una volta.

Un altro modo, utilizzando funzioni anonime:

// esegui il calcolo
$score = 'xxx';

add_filter('aioseop_title_single', function($title) use($score){
  return 'Risultati del Quiz (' . $score . ') - ' . $title;  
});
11 apr 2012 23:02:10
Commenti

Le funzioni anonime non dovrebbero essere utilizzate nelle chiamate add_filter() o add_action(). Non possono essere rimosse tramite remove_function().

Chip Bennett Chip Bennett
11 apr 2012 23:31:07

Intendi remove_filter, che viene principalmente utilizzato per rimuovere i filtri integrati, non i filtri aggiunti da plugin/temi...

onetrickpony onetrickpony
11 apr 2012 23:36:03

Sì; scusa: remove_filter() e remove_action(). E non c'è motivo per cui i filtri di Plugin/Temi non dovrebbero poter essere ragionevolmente rimossi: override degli stili enqueued dai Plugin, Child Themes, ecc.

Chip Bennett Chip Bennett
11 apr 2012 23:38:23
6

Il seguente esempio mostra la variabile $my_calculation nell'ambito globale, tuttavia dalla nostra funzione locale dobbiamo dichiarare global $my_calculation per poter accedere alla variabile nell'ambito globale.

<?php 

    $my_calculation = 'risultato!';

    function my_function() {

        global $my_calculation;
        return $my_calculation;

    }

    add_filter( 'function_something_here', 'my_function');   

?>

Questo è solo uno dei modi per procedere e sembra essere ordinato. Funzionerebbe per te?

11 apr 2012 22:57:06
Commenti

In cosa è diverso da quello che ha già?

onetrickpony onetrickpony
11 apr 2012 23:00:22

Una dichiarazione in meno di "global". Guarda il suo secondo esempio, dichiara global $wp due volte!

Adam Adam
11 apr 2012 23:02:47

Inoltre non funziona. Questa è la prima cosa che ho provato.

kingkool68 kingkool68
11 apr 2012 23:02:54

Sei in grado di print o echo il tuo risultato per assicurarti che la tua funzione stia effettivamente funzionando prima di passarla al filtro?

Adam Adam
11 apr 2012 23:04:27

Ops! Rendere globale $score funziona davvero. Ho sbagliato e ho impostato prima $score e poi l'ho globalizzato, cosa che chiaramente non funziona. Facendolo nel modo corretto, cioè globalizzando prima $score e poi assegnandogli un valore, funziona come previsto. Grazie a tutti.

kingkool68 kingkool68
11 apr 2012 23:12:57

Era quello che stavo per dirti dopo aver visto il tuo script, era un po' al contrario ;) Divertiti!

Adam Adam
11 apr 2012 23:14:01
Mostra i restanti 1 commenti