Cum să folosești do_action și să obții o valoare returnată?

21 apr. 2016, 19:47:49
Vizualizări: 21.2K
Voturi: 12

Iată următorul scenariu.

Adaug o acțiune pentru a curăța logurile din baza de date:

add_action( 'myplugin_clean_logs', array( 'MyPlugin_Logs', 'clean_logs' ) );

Acum vreau să rulez această acțiune periodic:

wp_schedule_event( current_time( 'timestamp' ), 'daily', 'myplugin_clean_logs' );

și să o execut manual:

do_action( 'myplugin_clean_logs' );

Metoda MyPlugin_Logs::clean_logs returnează numărul de rânduri afectate sau false dacă ceva nu a mers bine.

Acum vreau să afișez numărul de rânduri care au fost șterse. Mi-aș imagina ceva de genul:

$affected_rows = do_action( 'myplugin_clean_logs' );
echo $affected_rows . ' înregistrări au fost șterse.';

Dar cum do_action nu va returna nicio valoare, nu știu cum să obțin valoarea returnată.

Ar trebui să execut metoda direct la o rulare manuală, dar să folosesc acțiunea pentru evenimentele programate?

1
Comentarii

Nu dorești să afișezi nimic printr-un eveniment programat, deci da, aș executa metoda direct la o rulare manuală (presupun că administratorul ar declanșa acest lucru și vrei să-i arăți rezultatul).

Tim Malone Tim Malone
22 apr. 2016 01:55:28
Toate răspunsurile la întrebare 3
10
16

Partea interesantă este că un filtru este la fel ca o acțiune, doar că returnează o valoare, așa că pur și simplu configurează-l ca un filtru în loc de acțiune:

add_filter( 'myplugin_clean_logs', array( 'MyPlugin_Logs', 'clean_logs' ) );

Apoi ceva de genul:

$affected_rows = '';
$affected_rows = apply_filters( 'myplugin_clean_logs', $affected_rows );

ar trebui să transmită $affected_rows către clean_logs() (și orice alte funcții pe care le-ai conectat la myplugin_clean_logs) și să atribuie valoarea returnată înapoi la $affected_rows.

21 apr. 2016 21:18:22
Comentarii

am votat negativ deoarece acesta este un cod de hack în loc să fie dezvoltarea de software. Dacă acțiunile ar fi fost doar un subset de filtre, nu ar fi fost nevoie de ele. Cron nu poate transmite valori, prin urmare nu ar trebui să fie conectat ca un filtru, chiar dacă codul defectuos din nucleu vă permite să faceți astfel de scheme :)

Mark Kaplun Mark Kaplun
22 apr. 2016 00:27:11

Idee înțeleasă. Înțeleg intenția celor două lucruri diferite, dar uitându-mă la codul nucleului aici, întregul lucru do_action() nu este altceva decât un hack elaborat al apply_filters() :)

Caspar Caspar
22 apr. 2016 01:00:13

nu este singurul design prost din nucleu, ceea ce în parte duce la confuzii care conduc la întrebări ca aceasta

Mark Kaplun Mark Kaplun
22 apr. 2016 01:05:58

Trebuie să lucrăm cu ce avem, așa că în timp ce înțeleg punctul de vedere al lui Mark, tot cred că acesta este un răspuns legitim - cu excepția cazului în care, desigur, nucleul schimbă această abordare în viitor, dar cred că este puțin probabil din cauza problemelor masive de compatibilitate inversă pe care le-ar introduce.

Tim Malone Tim Malone
22 apr. 2016 01:57:48

Mulțumesc, @TimMalone. Apreciez obiecția lui @mark-kaplun. Răspunsul meu descrie cum să ocoliți faptul că do_action() nu returnează o valoare, mai degrabă decât să proiectați o soluție în concordanță cu intenția do_action(). Dacă cineva reușește să facă ceea ce cere el, acel răspuns merită să fie răspunsul acceptat. Prima mea idee ar fi ca metoda conectată (presupunând că OP folosește un design OOP pentru acest plugin) să își depună rezultatul într-o proprietate protejată a clasei plugin și apoi să scrieți o funcție rapidă pentru a-l extrage la un moment ulterior. Dar asta este doar o idee neclară!

Caspar Caspar
22 apr. 2016 05:05:51

@Casper documentația WordPress distinge explicit între acțiuni și filtre. Din câte am înțeles, un filtru este acolo pentru a filtra efectiv lucruri și, ca atare, este mai mult un instrument decât un executor. Poate că aceasta este doar teorie și mai mult o diferență de design de cod decât un caz din lumea reală. La început am avut o idee similară de a pasa o variabilă prin referință (deși nu am testat dacă funcționează), am evitat-o pentru a nu încurca codul.

Aley Aley
22 apr. 2016 10:22:12

@TimMalone, uneori când ai o problemă confuză de codare ar trebui să te oprești și să te întrebi dacă este o problemă de codare sau una de design

Mark Kaplun Mark Kaplun
22 apr. 2016 10:47:16

@Aley, scuze, de fapt am scris un comentariu la întrebare dar se pare că am uitat să-l trimit, dar poți înțelege esența a ceea ce cred (trebuie să o abordezi diferit în ambele cazuri) din comentariile de aici

Mark Kaplun Mark Kaplun
22 apr. 2016 10:48:28

De ce să nu folosești direct un apel de funcție PHP, astfel încât să nu ai nevoie de do_action sau apply_filters. Plasează funcția în fișierul functions.php.

Solomon Closson Solomon Closson
18 oct. 2016 21:39:25

Pentru ceea ce valorează, așa face WooCommerce în șabloanele lor. Teoria sau practicile recomandate la o parte, aceasta este în esență o metodă acceptată de a face lucrurile, deoarece WooCommerce face acum parte oficial din WordPress/Automattic.

Michael Thompson Michael Thompson
16 nov. 2016 22:16:59
Arată celelalte 5 comentarii
0

Aceasta este o întrebare foarte veche, dar pentru a răspunde la întrebarea originală "Cum să folosești do_action și să obții o valoare returnată?" pentru cei care caută, puteți face acest lucru folosind bufferizarea output-ului.

ob_start();
    do_action( 'myplugin_clean_logs' );
$action_data = ob_get_clean();

În acest fel puteți stoca conținutul do_action într-o variabilă.

20 iul. 2020 00:41:57
2

Niciodată nu am folosit această funcție și nu am testat-o, dar ar putea funcționa? do_action_ref_array().

function myplugin_clean_logs_fn() {
    $args = array(
        'param1'        => 'val1',
        'param2'        => 'val2',
        'affected_rows' => 0,
    );
    do_action_ref_array( 'myplugin_clean_logs', &$args );
    return $args['affected_rows'];
}

// APELARE
$affected_rows = my_plugin_clean_logs();
echo $affected_rows .' înregistrăr'. ($args['affected_rows']*1===1?'e':'i') .' șterse.';

// PROGRAMARE
add_action('myplugin_clean_logs_call_fn', 'myplugin_clean_logs_fn');
wp_schedule_event( current_time( 'timestamp' ), 'daily', 'myplugin_clean_logs_call_fn' );

// EXEMPLU DE FILTRU
add_action('myplugin_clean_logs', function($args) {
    // Proces de curățare
    // Pentru fiecare jurnal afectat, incrementați $args['affected_rows'] corespunzător
}, 10, 3);

Dacă nu funcționează, de ce să nu filtrezi pur și simplu așa cum a sugerat Caspar? Adică, acesta este scopul unui filtru, iar în acest caz numărul de rânduri afectate este lucrul care este filtrat. (Îmi lipsește vechiul MortCore. Își amintește cineva cum gestiona valorile de return, transmiterea prin referință și argumentele cu doar o singură funcție cu trei parametri?)

8 aug. 2019 22:54:27
Comentarii

Acesta este un răspuns oribil, deoarece transmiterea și modificarea valorilor prin referință este o practică foarte proastă. Sincer, acest răspuns nu aduce nicio valoare în contextul întrebării și ar trebui fie eliminat, fie schimbat într-un comentariu. În plus, utilizarea funcțiilor anonime cu hook-uri este de asemenea o practică proastă, deoarece le face imposibil de dezactivat.

Hybrid Web Dev Hybrid Web Dev
30 oct. 2019 23:12:07

Sunt de acord pentru aceleași motive menționate mai sus, că aceasta nu este o cale recomandată. Dacă din anumite motive ai nevoie să obții o valoare de return dintr-o acțiune și ai nevoie de ceva rapid și murdar, aș prefera soluția lui Caspar. Dacă dezvolți ceva cu un ciclu de viață mai lung, aș căuta o metodă mai robustă. Venind la idee, ce zici de notificările de administrare? https://developer.wordpress.org/reference/hooks/admin_notices/

jgangso jgangso
21 ian. 2020 11:55:50