Come utilizzare do_action e ottenere un valore di ritorno?

21 apr 2016, 19:47:49
Visualizzazioni: 21.2K
Voti: 12

Ecco il seguente scenario.

Aggiungo un'azione per pulire i log dal database:

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

Ora voglio eseguire questa azione periodicamente:

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

ed eseguirla manualmente:

do_action( 'myplugin_clean_logs' );

Il metodo MyPlugin_Logs::clean_logs restituisce il conteggio delle righe interessate o false se qualcosa è andato nell'altra direzione.

Ora voglio visualizzare il numero di righe che sono state eliminate. Immaginerei qualcosa del genere:

$affected_rows = do_action( 'myplugin_clean_logs' );
echo $affected_rows . ' elementi sono stati eliminati.';

Ma poiché do_action non restituirà alcun valore, non ho idea di come ottenere il valore di ritorno.

Dovrei eseguire il metodo direttamente in un'esecuzione manuale, ma utilizzare l'azione sugli eventi programmati?

1
Commenti

Non vuoi che venga emesso alcun output durante un evento pianificato, quindi sì, eseguirei il metodo direttamente durante un avvio manuale (presumo che sia l'amministratore a triggerarlo e che tu voglia mostrargli l'output).

Tim Malone Tim Malone
22 apr 2016 01:55:28
Tutte le risposte alla domanda 3
10
16

La cosa interessante è che un filtro è uguale a un'azione, solo che restituisce un valore, quindi basta configurarlo come filtro invece:

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

Poi qualcosa come:

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

dovrebbe passare $affected_rows a clean_logs() (e a qualsiasi altra funzione che hai collegato a myplugin_clean_logs) e assegnare il valore restituito nuovamente a $affected_rows.

21 apr 2016 21:18:22
Commenti

votato negativamente perché questo è hacking del codice invece di sviluppare software. Se le azioni fossero solo un sottoinsieme dei filtri non ci sarebbe stato alcun bisogno di loro. Cron non può passare valori quindi non dovrebbe essere agganciato come un filtro anche se il codice problematico del core ti permette di fare questi trucchetti :)

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

Punto preso. Capisco l'intento delle due cose diverse, ma guardando il codice del core qui, tutta la faccenda di do_action() non è altro che un elaborato hack di apply_filters() :)

Caspar Caspar
22 apr 2016 01:00:13

non è l'unico cattivo design nel core che in parte è ciò che porta alla confusione che genera domande come questa

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

Dobbiamo lavorare con quello che abbiamo, quindi mentre capisco il punto di vista di Mark penso ancora che questa sia una risposta legittima - a meno che ovviamente il core non cambi questo approccio in futuro, ma penso che sia improbabile a causa degli enormi problemi di retrocompatibilità che introdurrebbe.

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

Grazie, @TimMalone. Apprezzo l'obiezione di @mark-kaplun. La mia risposta descrive come aggirare il fatto che do_action() non restituisce un valore piuttosto che come progettare una soluzione in linea con l'intento di do_action(). Se qualcuno è in grado di fare ciò che chiede, quella risposta merita di essere quella accettata. La mia prima idea sarebbe di far sì che il metodo agganciato (supponendo che l'OP stia usando un design OOP per questo plugin) inserisca il suo risultato in una proprietà protetta della classe del plugin e poi scrivere un rapido getter per estrarlo in un secondo momento. Ma è solo un'idea improvvisata!

Caspar Caspar
22 apr 2016 05:05:51

@Casper la documentazione di wordpress distingue esplicitamente tra azioni e filtri. Per quanto ho capito, un filtro è lì per filtrare effettivamente le cose ed è come tale più uno strumento che un esecutore. Forse questa è solo teoria e più una differenza di design del codice che un caso reale. All'inizio ho avuto un'idea simile di passare una variabile per riferimento (anche se non l'ho testato, per vedere se funziona), l'ho evitata per non incasinare il codice.

Aley Aley
22 apr 2016 10:22:12

@TimMalone, a volte quando hai un problema di codifica confuso dovresti fermarti e chiederti se è un problema di codifica o un problema di design

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

@Aley, scusa in realtà avevo scritto un commento alla domanda ma apparentemente ho dimenticato di inviarlo, ma puoi capire cosa penso (devi gestirlo diversamente in entrambi i casi) dai commenti qui

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

Perché non usare invece una chiamata a funzione PHP, in questo modo non c'è bisogno di do_action o apply_filters. Inserisci la funzione nel file functions.php.

Solomon Closson Solomon Closson
18 ott 2016 21:39:25

Per quel che vale, questo è il modo in cui WooCommerce lo fa nei suoi template. A parte teoria o best practice, questo è essenzialmente un modo accettato di fare le cose dato che WooCommerce è ora ufficialmente parte di Wordpress/Automattic.

Michael Thompson Michael Thompson
16 nov 2016 22:16:59
Mostra i restanti 5 commenti
0

Questa è una domanda molto vecchia, ma per rispondere alla domanda originale "Come fare do_action e ottenere un valore di ritorno?" per chiunque stia cercando, puoi farlo utilizzando l'output buffering.

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

In questo modo puoi memorizzare il contenuto di do_action in una variabile.

20 lug 2020 00:41:57
2

Non ho mai usato questa funzione e non l'ho testata, ma potrebbe funzionare? 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'];
}

// CHIAMALA
$affected_rows = my_plugin_clean_logs();
echo $affected_rows .' rig'. ($args['affected_rows']*1===1?'a':'he') .' cancellata.';

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

// UN FILTRO DI ESEMPIO
add_action('myplugin_clean_logs', function($args) {
    // Processo di pulizia
    // Per ogni log interessato, incrementa $args['affected_rows'] di conseguenza
}, 10, 3);

Se non funziona, perché non filtrare semplicemente la cosa come ha suggerito Caspar? Voglio dire, questo è lo scopo di un filtro, e in questo caso il numero di righe interessate è ciò che viene filtrato. (Mi manca il vecchio MortCore. Qualcuno ricorda come gestiva i valori di ritorno, il passaggio per riferimento e gli argomenti con una singola funzione a tre parametri?)

8 ago 2019 22:54:27
Commenti

Questa è una risposta pessima, poiché passare e modificare valori per riferimento è una pratica davvero sconsigliata. Sinceramente, questa risposta non fornisce alcun valore nel contesto della domanda e dovrebbe probabilmente essere rimossa o trasformata in un commento. Inoltre, utilizzare funzioni anonime con gli hook è altrettanto sconsigliato, poiché le rende impossibili da scollegare.

Hybrid Web Dev Hybrid Web Dev
30 ott 2019 23:12:07

Concordo per le stesse ragioni sopra citate, che questa non sia una strada raccomandata. Se per qualche motivo hai bisogno di ottenere un valore di ritorno da un'azione e ti serve qualcosa di rapido e sporadico, preferirei la soluzione di Caspar. Se stai sviluppando qualcosa con un ciclo di vita davanti, cercerei un modo più robusto. A pensarci bene, che ne dici degli admin notices? https://developer.wordpress.org/reference/hooks/admin_notices/

jgangso jgangso
21 gen 2020 11:55:50