Cum să transmiți variabile externe către filtre/acțiuni WordPress
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
Aveți cel puțin două opțiuni:
- Globalizați variabila dorită, apoi faceți referire la ea în interiorul callback-ului
- Î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')
.

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

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.

Î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!

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

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. :)

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?

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

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 :)

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ă.

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ă.

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.

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

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.

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.

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

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

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

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?

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

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

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?

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.
