Cum să transmiți variabile externe către filtre/acțiuni WordPress

11 apr. 2012, 22:37:25
Vizualizări: 25.3K
Voturi: 12

Mă confrunt cu nevoia de a transmite date personalizate către un filtru furnizat de un plugin terț. Toate metodele pe care le-am văzut până acum sunt foarte complicate și greu de înțeles.

Iată un exemplu:

$score = 42; //Un calcul complex pe care nu vreau să-l repet

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

add_filter( 'aioseop_title_single', 'add_score_to_title');

Cum pot transmite variabila $score către funcția add_score_to_title()?

Ceea ce am făcut până la urmă a fost să adaug variabila mea în obiectul global $wp. Așa că am ajuns la următoarea soluție:

global $wp;
$score = 42; //Un calcul complex pe care nu vreau să-l repet
$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');

Neconvențional? Poate. Simplu? Da! Există dezavantaje pentru această tehnică? Vă rog să discutăm.

ACTUALIZARE Aici este codul complet în discuție -> http://pastebin.com/fkSXY04m

5
Comentarii

Pur și simplu faci „calculul tău nebun” în interiorul acelei funcții...

onetrickpony onetrickpony
11 apr. 2012 22:45:42

Probabil este greu de înțeles din exemplul meu simplificat. Variabila $score este folosită pe tot parcursul acelui șablon. Vreau să o calculez o singură dată și să transmit acea valoare către funcția care este un callback pentru un filtru de modificare a titlului paginii. Acest filtru este folosit în All In One SEO Pack. Nu este de dorit să rulez calculul de mai multe ori.

kingkool68 kingkool68
11 apr. 2012 22:54:33

Atunci ar trebui să postezi mai mult cod dacă vrei să obții o soluție care nu implică introducerea unei stări globale (ceea ce nu ar trebui să fie necesar niciodată).

onetrickpony onetrickpony
11 apr. 2012 23:00:03

Iată codul complet într-un fișier șablon. $score este calculat prin iterarea unui array de elemente și incrementarea unei variabile.

http://pastebin.com/fkSXY04m

kingkool68 kingkool68
11 apr. 2012 23:07:43

posibil duplicat al Transmiterii unui parametru către funcțiile de filtrare și acțiune

T.Todua T.Todua
14 mai 2015 12:20:32
Toate răspunsurile la întrebare 3
14
12

Aveți cel puțin două opțiuni:

  1. Globalizați variabila dorită, apoi faceți referire la ea în interiorul callback-ului
  2. Încapsulați logica de calcul a scorului într-o funcție, apoi faceți referire la ea în interiorul callback-ului

Globalizarea Variabilei

<?php
global $score;
$score = 42; //Un calcul nebun pe care nu vreau să-l repet.

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

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

Încapsularea Calculului Scorului

Dacă aveți nevoie de calculul scorului doar în interiorul filtrului, mutați logica în callback-ul însuși:

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

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

Și mai bine, puteți încapsula calculul scorului într-o funcție separată, apoi apelați acea funcție în interiorul callback-ului:

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

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

Dacă întâmpinați probleme la referirea obiectului $_POST, puteți de asemenea să înregistrați variabila de interogare și apoi să folosiți get_query_var() intern pentru a obține datele:

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

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

Cu această implementare, $_POST['Q'] poate fi înlocuit cu get_query_var('Q').

11 apr. 2012 22:44:34
Comentarii

Acest lucru nu are nicio legătură cu numărul de argumente transmise funcției prin apply_filters...

onetrickpony onetrickpony
11 apr. 2012 22:46:40

Am încercat metoda #1 pe care o menționați de a globaliza variabila. Nu funcționează. Parametrul accepted args nu mă ajută nici el, deoarece nu am control asupra variabilelor transmise funcției callback.

kingkool68 kingkool68
11 apr. 2012 22:55:58

Îmi pare rău, ai avut dreptate. Am calculat mai întâi $score și apoi l-am globalizat. Nu e de mirare că nu a funcționat. Mulțumesc!

kingkool68 kingkool68
11 apr. 2012 23:11:35

-1. Prima opțiune expune o variabilă în starea globală, a doua opțiune nu funcționează...

onetrickpony onetrickpony
11 apr. 2012 23:28:23

Actualizat pentru a reflecta faptul că am greșit la a doua opțiune. Dar ce e rău în a expune o variabilă globală? Este cu siguranță mai bine decât a folosi o funcție anonimă într-un callback. :)

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

Nu, nu este. Și aici sunt câteva motive pentru care ar trebui să eviți această practică. Poate că este ok pentru cazul său specific, dar dacă cineva chiar construiește un plugin public folosind soluția ta?

onetrickpony onetrickpony
11 apr. 2012 23:34:10

"Variabilele globale sunt rele"? Serios? Atunci întregul cod WordPress ar trebui rescris, deoarece se bazează pe destul de multe variabile globale.

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

Exact. Acesta este unul dintre motivele pentru care codul de bază al WP este unul dintre cele mai slabe de pe web. Oricum, WP are o scuză - necesitatea de compatibilitate cu plugin-uri concepute pentru versiuni mai vechi. Tu nu ai :)

onetrickpony onetrickpony
11 apr. 2012 23:38:44

Da... o să las asta așa cum e. Mulțumesc pentru sublinierea problemei cu a doua opțiune; am eliminat-o din întrebare. Susțin acceptabilitatea utilizării variabilelor globale. Dacă aș ști cum este generată sau returnată ieșirea Plugin-ului, probabil aș putea oferi o soluție mai bună.

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

Vezi răspunsul actualizat; după ce am analizat Pastebin-ul, am oferit două metode pe care le-aș prefera în loc să folosesc o variabilă globală.

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

Mai bine, dar el vrea ca „scorul” să fie accesibil mai târziu în script, fără a fi recalculat, așa că utilizarea unei variabile „statice” are sens aici.

onetrickpony onetrickpony
11 apr. 2012 23:57:55

Folosind o funcție pentru a calcula scorul: nu ar putea fi stocat calculul în cache-ul de obiecte?

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

toamna anului 2015 și WP încă se bazează pe variabile globale rele. Scuza a devenit prea veche. Și +1 pentru sugestia de globalizare. În cazul meu, callback-ul trebuia să acceseze $user pe care a trebuit să îl globalizez deoarece apelul meu apply_filters era inițiat din interiorul unei funcții.

Ejaz Ejaz
7 oct. 2015 20:56:50

Aceste globale sunt rele, oamenii trebuie să se calmeze. Îmi place destul de mult acest răspuns. OP a întrebat cum pot fi transmise variabile între funcții. Acest răspuns explică mai multe moduri de a face asta. Începe cu globalele, care sunt de evitat, dar totuși există și rezolvă problema la îndemână. Apoi răspunsul continuă să explice mai multe opțiuni mai bune care ar putea funcționa în anumite circumstanțe.

squarecandy squarecandy
21 sept. 2017 18:25:43
Arată celelalte 9 comentarii
3
function add_score_to_title($title = false) {
  static $score = false;

  if($score === false){
    // facem calculul
  }

  // apel plugin (filtru)   
  if($title !== false)
    return 'Rezultate Test (' . $score . ') - ' . $title;

  // apel direct
  return $score;
}

Apelează funcția în orice parte a scriptului pentru a obține scorul, acesta va fi calculat o singură dată.

O altă metodă, folosind funcții anonime:

// facem calculul
$score = 'xxx';

add_filter('aioseop_title_single', function($title) use($score){
  return 'Rezultate Test (' . $score . ') - ' . $title;  
});
11 apr. 2012 23:02:10
Comentarii

Funcțiile anonime nu ar trebui folosite în apelurile add_filter() sau add_action(). Ele nu pot fi eliminate prin remove_function().

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

Te referi la remove_filter, care este folosit în principal pentru a elimina filtrele integrate, nu cele adăugate de plugin-uri/teme...

onetrickpony onetrickpony
11 apr. 2012 23:36:03

Da; scuze: remove_filter() și remove_action(). Și nu există niciun motiv pentru care filtrele Plugin-urilor/Temelor să nu poată fi eliminate în mod rezonabil: suprascrierea încărcărilor de fișiere CSS ale Plugin-urilor, Temele Copil, etc.

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

Următorul exemplu include variabila $my_calculation în domeniul global, dar din interiorul funcției noastre locale trebuie să declarăm global $my_calculation pentru a accesa variabila în domeniul global.

<?php 

    $my_calculation = 'rezultat!';

    function my_function() {

        global $my_calculation;
        return $my_calculation;

    }

    add_filter( 'function_something_here', 'my_function');   

?>

Acesta este doar un mod de a aborda situația și pare a fi ordonat. Funcționează pentru tine?

11 apr. 2012 22:57:06
Comentarii

În ce fel este acest lucru diferit de ceea ce are deja?

onetrickpony onetrickpony
11 apr. 2012 23:00:22

Încă o declarație în minus de "global". Uită-te la al doilea exemplu al lui, declară gloabl $wp de două ori!

Adam Adam
11 apr. 2012 23:02:47

De asemenea, nu funcționează. Acesta este primul lucru pe care l-am încercat.

kingkool68 kingkool68
11 apr. 2012 23:02:54

Poți să folosești print sau echo pentru a afișa rezultatul tău și a te asigura că funcția ta funcționează corect înainte de a o transmite filtrului?

Adam Adam
11 apr. 2012 23:04:27

Ups! Globalizarea variabilei $score funcționează într-adevăr. Am greșit și am setat mai întâi valoarea pentru $score și abia apoi am globalizat-o, ceea ce evident nu funcționează. Făcând corect, prin globalizarea variabilei $score mai întâi și apoi atribuirea unei valori, funcționează conform așteptărilor. Mulțumesc tuturor.

kingkool68 kingkool68
11 apr. 2012 23:12:57

Tocmai asta aveam să-ți spun și eu după ce am văzut scriptul tău, era puțin inversat ;) Distracție plăcută!

Adam Adam
11 apr. 2012 23:14:01
Arată celelalte 1 comentarii