Bagaimana caranya melakukan_aksi dan mendapatkan nilai balik?

10

Jadi ada skenario berikut.

Saya menambahkan tindakan untuk membersihkan log dari database:

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

Sekarang saya ingin menjalankan tindakan ini secara berkala:

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

dan jalankan secara manual:

do_action( 'myplugin_clean_logs' );

Metode MyPlugin_Logs::clean_logsmengembalikan jumlah baris yang terpengaruh atau salah jika ada sesuatu yang berlawanan arah.

Sekarang saya ingin menampilkan jumlah baris yang telah dihapus. Saya akan membayangkan sesuatu seperti ini:

$affected_rows = do_action( 'myplugin_clean_logs' );
echo $affected_rows . ' entries have been deleted.';

Tetapi karena do_actiontidak akan mengembalikan nilai apa pun, saya tidak tahu cara mendapatkan nilai kembali.

Haruskah saya mengeksekusi metode langsung pada menjalankan manual, tetapi menggunakan tindakan pada jadwal acara?

Aley
sumber
1
Anda tidak ingin menggemakan apa pun pada acara yang dijadwalkan, jadi ya, saya akan menjalankan metode ini secara manual (saya berasumsi administrator akan memicu ini, dan Anda ingin menunjukkan hasilnya kepada mereka).
Tim Malone

Jawaban:

13

Yang keren adalah filter sama dengan tindakan, hanya saja mengembalikan nilai, jadi setel saja sebagai filter:

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

Maka sesuatu seperti:

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

harus diteruskan $affected_rowske clean_logs()(dan fungsi apa pun yang mungkin Anda kaitkan myplugin_clean_logs) dan menetapkan kembali nilai kembali $affected_rows.

Caspar
sumber
4
downvoted karena ini adalah kode peretasan daripada mengembangkan perangkat lunak. Jika tindakan hanya sebagian dari filter, tidak akan ada kebutuhan mereka. Cron tidak dapat melewatkan nilai karenanya tidak boleh dikaitkan sebagai filter bahkan jika kode inti buggy memungkinkan Anda untuk melakukan shemigans seperti itu :)
Mark Kaplun
1
Poin yang diambil. Saya mendapatkan maksud dari dua hal yang berbeda, tetapi untuk melihat kode inti di sini, do_action()semuanya tidak lebih dari perincian rumit apply_filters():)
Caspar
bukan satu-satunya desain buruk di inti yang sebagian menyebabkan kebingungan yang mengarah pada pertanyaan seperti ini
Mark Kaplun
1
Kita perlu bekerja dengan apa yang kita miliki, jadi sementara saya mengerti sudut pandang Mark, saya masih berpikir ini adalah jawaban yang sah - kecuali tentu saja inti mengubah pendekatan ini di masa depan, tapi saya pikir itu tidak mungkin karena masalah kompatibilitas ke belakang yang masif. itu akan memperkenalkan.
Tim Malone
3
Terima kasih, @TimMalone. Saya menghargai keberatan @ mark-kaplun. Jawaban saya menjelaskan bagaimana mengatasi do_action()tidak mengembalikan nilai daripada bagaimana merancang solusi yang sesuai dengan do_action()niat. Jika seseorang mampu melakukan apa yang dia minta, jawaban itu pantas menjadi jawaban yang diterima. Pikiran pertama saya adalah memiliki metode bengkok (dengan asumsi OP menggunakan desain OOP untuk plugin ini) jatuhkan hasilnya ke properti yang dilindungi dari kelas plugin dan kemudian menulis getter cepat untuk menariknya di beberapa titik kemudian. Tapi itu hanya ide liar!
Caspar
-1

Tidak pernah menggunakan fungsi ini dan belum menguji ini, tetapi mungkinkah ini berfungsi? 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'];
}

// CALL IT
$affected_rows = my_plugin_clean_logs();
echo $affected_rows .' entr'. ($args['affected_rows']*1===1?'y':'ies') .' deleted.';

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

// A SAMPLE FILTER
add_action('myplugin_clean_logs', function($args) {
    // Cleaning process
    // For each log affected, increment $args['affected_rows'] accordingly
}, 10, 3);

Jika itu tidak berhasil, mengapa tidak menyaring hal seperti yang disarankan Caspar? Maksud saya, itu adalah tujuan dari filter, dan dalam hal ini jumlah baris yang terpengaruh adalah hal yang disaring. (Saya merindukan MortCore yang lama. Adakah yang ingat bagaimana ia menangani nilai balik, pass-by-reference, dan argumen hanya dengan fungsi tiga parameter tunggal?)

Bola Goof
sumber
Ini adalah jawaban yang mengerikan, karena menyerahkan dan memodifikasi nilai dengan referensi adalah praktik yang sangat buruk. Jujur, jawaban ini benar-benar tidak memberikan nilai dalam konteks pertanyaan dan kemungkinan harus dihapus atau diubah menjadi komentar. Selain itu, menggunakan fungsi anonim dengan kait juga merupakan praktik yang buruk, karena membuat mereka tidak mungkin dilepas.
Web Dev Hybrid
Saya setuju untuk alasan yang disebutkan di atas, bahwa ini bukan jalan yang disarankan. Jika Anda karena alasan tertentu perlu mendapatkan nilai kembali dari suatu tindakan, dan butuh sesuatu yang cepat dan kotor, saya lebih suka solusi Kaspars. Jika Anda mengembangkan sesuatu dengan siklus hidup di depannya, saya akan mencari cara yang lebih kuat. Kalau dipikir-pikir, bagaimana dengan pemberitahuan admin? developer.wordpress.org/reference/hooks/admin_notices
jgangso